/*! * 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); // common/dist/esm/backend-impl.js var backends, backendsSortedByPriority, registerBackend, tryResolveAndInitializeBackend, resolveBackendAndExecutionProviders; var init_backend_impl = __esm({ "common/dist/esm/backend-impl.js"() { "use strict"; backends = /* @__PURE__ */ new Map(); backendsSortedByPriority = []; registerBackend = (name, backend, priority) => { if (backend && typeof backend.init === "function" && typeof backend.createInferenceSessionHandler === "function") { const currentBackend = backends.get(name); if (currentBackend === void 0) { backends.set(name, { backend, priority }); } else if (currentBackend.priority > priority) { return; } else if (currentBackend.priority === priority) { if (currentBackend.backend !== backend) { throw new Error(`cannot register backend "${name}" using priority ${priority}`); } } if (priority >= 0) { const i = backendsSortedByPriority.indexOf(name); if (i !== -1) { backendsSortedByPriority.splice(i, 1); } for (let i2 = 0; i2 < backendsSortedByPriority.length; i2++) { if (backends.get(backendsSortedByPriority[i2]).priority <= priority) { backendsSortedByPriority.splice(i2, 0, name); return; } } backendsSortedByPriority.push(name); } return; } throw new TypeError("not a valid backend"); }; tryResolveAndInitializeBackend = async (backendName) => { const backendInfo = backends.get(backendName); if (!backendInfo) { return "backend not found."; } if (backendInfo.initialized) { return backendInfo.backend; } else if (backendInfo.aborted) { return backendInfo.error; } else { const isInitializing = !!backendInfo.initPromise; try { if (!isInitializing) { backendInfo.initPromise = backendInfo.backend.init(backendName); } await backendInfo.initPromise; backendInfo.initialized = true; return backendInfo.backend; } catch (e) { if (!isInitializing) { backendInfo.error = `${e}`; backendInfo.aborted = true; } return backendInfo.error; } finally { delete backendInfo.initPromise; } } }; resolveBackendAndExecutionProviders = async (options) => { const eps = options.executionProviders || []; const backendHints = eps.map((i) => typeof i === "string" ? i : i.name); const backendNames = backendHints.length === 0 ? backendsSortedByPriority : backendHints; let backend; const errors = []; const availableBackendNames = /* @__PURE__ */ new Set(); for (const backendName of backendNames) { const resolveResult = await tryResolveAndInitializeBackend(backendName); if (typeof resolveResult === "string") { errors.push({ name: backendName, err: resolveResult }); } else { if (!backend) { backend = resolveResult; } if (backend === resolveResult) { availableBackendNames.add(backendName); } } } if (!backend) { throw new Error(`no available backend found. ERR: ${errors.map((e) => `[${e.name}] ${e.err}`).join(", ")}`); } for (const { name, err } of errors) { if (backendHints.includes(name)) { console.warn(`removing requested execution provider "${name}" from session options because it is not available: ${err}`); } } const filteredEps = eps.filter((i) => availableBackendNames.has(typeof i === "string" ? i : i.name)); return [ backend, new Proxy(options, { get: (target, prop) => { if (prop === "executionProviders") { return filteredEps; } return Reflect.get(target, prop); } }) ]; }; } }); // common/dist/esm/backend.js var init_backend = __esm({ "common/dist/esm/backend.js"() { "use strict"; init_backend_impl(); } }); // common/dist/esm/version.js var version; var init_version = __esm({ "common/dist/esm/version.js"() { "use strict"; version = "1.23.0"; } }); // common/dist/esm/env-impl.js var logLevelValue, env; var init_env_impl = __esm({ "common/dist/esm/env-impl.js"() { "use strict"; init_version(); logLevelValue = "warning"; env = { wasm: {}, webgl: {}, webgpu: {}, versions: { common: version }, set logLevel(value) { if (value === void 0) { return; } if (typeof value !== "string" || ["verbose", "info", "warning", "error", "fatal"].indexOf(value) === -1) { throw new Error(`Unsupported logging level: ${value}`); } logLevelValue = value; }, get logLevel() { return logLevelValue; } }; Object.defineProperty(env, "logLevel", { enumerable: true }); } }); // common/dist/esm/env.js var env2; var init_env = __esm({ "common/dist/esm/env.js"() { "use strict"; init_env_impl(); env2 = env; } }); // common/dist/esm/tensor-conversion-impl.js var tensorToDataURL, tensorToImageData; var init_tensor_conversion_impl = __esm({ "common/dist/esm/tensor-conversion-impl.js"() { "use strict"; tensorToDataURL = (tensor, options) => { const canvas = typeof document !== "undefined" ? document.createElement("canvas") : new OffscreenCanvas(1, 1); canvas.width = tensor.dims[3]; canvas.height = tensor.dims[2]; const pixels2DContext = canvas.getContext("2d"); if (pixels2DContext != null) { let width; let height; if (options?.tensorLayout !== void 0 && options.tensorLayout === "NHWC") { width = tensor.dims[2]; height = tensor.dims[3]; } else { width = tensor.dims[3]; height = tensor.dims[2]; } const inputformat = options?.format !== void 0 ? options.format : "RGB"; const norm = options?.norm; let normMean; let normBias; if (norm === void 0 || norm.mean === void 0) { normMean = [255, 255, 255, 255]; } else { if (typeof norm.mean === "number") { normMean = [norm.mean, norm.mean, norm.mean, norm.mean]; } else { normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 0]; if (norm.mean[3] !== void 0) { normMean[3] = norm.mean[3]; } } } if (norm === void 0 || norm.bias === void 0) { normBias = [0, 0, 0, 0]; } else { if (typeof norm.bias === "number") { normBias = [norm.bias, norm.bias, norm.bias, norm.bias]; } else { normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0]; if (norm.bias[3] !== void 0) { normBias[3] = norm.bias[3]; } } } const stride = height * width; let rTensorPointer = 0, gTensorPointer = stride, bTensorPointer = stride * 2, aTensorPointer = -1; if (inputformat === "RGBA") { rTensorPointer = 0; gTensorPointer = stride; bTensorPointer = stride * 2; aTensorPointer = stride * 3; } else if (inputformat === "RGB") { rTensorPointer = 0; gTensorPointer = stride; bTensorPointer = stride * 2; } else if (inputformat === "RBG") { rTensorPointer = 0; bTensorPointer = stride; gTensorPointer = stride * 2; } for (let i = 0; i < height; i++) { for (let j = 0; j < width; j++) { const R = (tensor.data[rTensorPointer++] - normBias[0]) * normMean[0]; const G = (tensor.data[gTensorPointer++] - normBias[1]) * normMean[1]; const B = (tensor.data[bTensorPointer++] - normBias[2]) * normMean[2]; const A = aTensorPointer === -1 ? 255 : (tensor.data[aTensorPointer++] - normBias[3]) * normMean[3]; pixels2DContext.fillStyle = "rgba(" + R + "," + G + "," + B + "," + A + ")"; pixels2DContext.fillRect(j, i, 1, 1); } } if ("toDataURL" in canvas) { return canvas.toDataURL(); } else { throw new Error("toDataURL is not supported"); } } else { throw new Error("Can not access image data"); } }; tensorToImageData = (tensor, options) => { const pixels2DContext = typeof document !== "undefined" ? document.createElement("canvas").getContext("2d") : new OffscreenCanvas(1, 1).getContext("2d"); let image; if (pixels2DContext != null) { let width; let height; let channels; if (options?.tensorLayout !== void 0 && options.tensorLayout === "NHWC") { width = tensor.dims[2]; height = tensor.dims[1]; channels = tensor.dims[3]; } else { width = tensor.dims[3]; height = tensor.dims[2]; channels = tensor.dims[1]; } const inputformat = options !== void 0 ? options.format !== void 0 ? options.format : "RGB" : "RGB"; const norm = options?.norm; let normMean; let normBias; if (norm === void 0 || norm.mean === void 0) { normMean = [255, 255, 255, 255]; } else { if (typeof norm.mean === "number") { normMean = [norm.mean, norm.mean, norm.mean, norm.mean]; } else { normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 255]; if (norm.mean[3] !== void 0) { normMean[3] = norm.mean[3]; } } } if (norm === void 0 || norm.bias === void 0) { normBias = [0, 0, 0, 0]; } else { if (typeof norm.bias === "number") { normBias = [norm.bias, norm.bias, norm.bias, norm.bias]; } else { normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0]; if (norm.bias[3] !== void 0) { normBias[3] = norm.bias[3]; } } } const stride = height * width; if (options !== void 0) { if (options.format !== void 0 && channels === 4 && options.format !== "RGBA" || channels === 3 && options.format !== "RGB" && options.format !== "BGR") { throw new Error("Tensor format doesn't match input tensor dims"); } } const step = 4; let rImagePointer = 0, gImagePointer = 1, bImagePointer = 2, aImagePointer = 3; let rTensorPointer = 0, gTensorPointer = stride, bTensorPointer = stride * 2, aTensorPointer = -1; if (inputformat === "RGBA") { rTensorPointer = 0; gTensorPointer = stride; bTensorPointer = stride * 2; aTensorPointer = stride * 3; } else if (inputformat === "RGB") { rTensorPointer = 0; gTensorPointer = stride; bTensorPointer = stride * 2; } else if (inputformat === "RBG") { rTensorPointer = 0; bTensorPointer = stride; gTensorPointer = stride * 2; } image = pixels2DContext.createImageData(width, height); for (let i = 0; i < height * width; rImagePointer += step, gImagePointer += step, bImagePointer += step, aImagePointer += step, i++) { image.data[rImagePointer] = (tensor.data[rTensorPointer++] - normBias[0]) * normMean[0]; image.data[gImagePointer] = (tensor.data[gTensorPointer++] - normBias[1]) * normMean[1]; image.data[bImagePointer] = (tensor.data[bTensorPointer++] - normBias[2]) * normMean[2]; image.data[aImagePointer] = aTensorPointer === -1 ? 255 : (tensor.data[aTensorPointer++] - normBias[3]) * normMean[3]; } } else { throw new Error("Can not access image data"); } return image; }; } }); // common/dist/esm/tensor-factory-impl.js var bufferToTensor, tensorFromImage, tensorFromTexture, tensorFromGpuBuffer, tensorFromMLTensor, tensorFromPinnedBuffer; var init_tensor_factory_impl = __esm({ "common/dist/esm/tensor-factory-impl.js"() { "use strict"; init_tensor_impl(); bufferToTensor = (buffer, options) => { if (buffer === void 0) { throw new Error("Image buffer must be defined"); } if (options.height === void 0 || options.width === void 0) { throw new Error("Image height and width must be defined"); } if (options.tensorLayout === "NHWC") { throw new Error("NHWC Tensor layout is not supported yet"); } const { height, width } = options; const norm = options.norm ?? { mean: 255, bias: 0 }; let normMean; let normBias; if (typeof norm.mean === "number") { normMean = [norm.mean, norm.mean, norm.mean, norm.mean]; } else { normMean = [norm.mean[0], norm.mean[1], norm.mean[2], norm.mean[3] ?? 255]; } if (typeof norm.bias === "number") { normBias = [norm.bias, norm.bias, norm.bias, norm.bias]; } else { normBias = [norm.bias[0], norm.bias[1], norm.bias[2], norm.bias[3] ?? 0]; } const inputformat = options.format !== void 0 ? options.format : "RGBA"; const outputformat = options.tensorFormat !== void 0 ? options.tensorFormat !== void 0 ? options.tensorFormat : "RGB" : "RGB"; const stride = height * width; const float32Data = outputformat === "RGBA" ? new Float32Array(stride * 4) : new Float32Array(stride * 3); let step = 4, rImagePointer = 0, gImagePointer = 1, bImagePointer = 2, aImagePointer = 3; let rTensorPointer = 0, gTensorPointer = stride, bTensorPointer = stride * 2, aTensorPointer = -1; if (inputformat === "RGB") { step = 3; rImagePointer = 0; gImagePointer = 1; bImagePointer = 2; aImagePointer = -1; } if (outputformat === "RGBA") { aTensorPointer = stride * 3; } else if (outputformat === "RBG") { rTensorPointer = 0; bTensorPointer = stride; gTensorPointer = stride * 2; } else if (outputformat === "BGR") { bTensorPointer = 0; gTensorPointer = stride; rTensorPointer = stride * 2; } for (let i = 0; i < stride; i++, rImagePointer += step, bImagePointer += step, gImagePointer += step, aImagePointer += step) { float32Data[rTensorPointer++] = (buffer[rImagePointer] + normBias[0]) / normMean[0]; float32Data[gTensorPointer++] = (buffer[gImagePointer] + normBias[1]) / normMean[1]; float32Data[bTensorPointer++] = (buffer[bImagePointer] + normBias[2]) / normMean[2]; if (aTensorPointer !== -1 && aImagePointer !== -1) { float32Data[aTensorPointer++] = (buffer[aImagePointer] + normBias[3]) / normMean[3]; } } const outputTensor = outputformat === "RGBA" ? new Tensor("float32", float32Data, [1, 4, height, width]) : new Tensor("float32", float32Data, [1, 3, height, width]); return outputTensor; }; tensorFromImage = async (image, options) => { const isHTMLImageEle = typeof HTMLImageElement !== "undefined" && image instanceof HTMLImageElement; const isImageDataEle = typeof ImageData !== "undefined" && image instanceof ImageData; const isImageBitmap = typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap; const isString = typeof image === "string"; let data; let bufferToTensorOptions = options ?? {}; const createCanvas = () => { if (typeof document !== "undefined") { return document.createElement("canvas"); } else if (typeof OffscreenCanvas !== "undefined") { return new OffscreenCanvas(1, 1); } else { throw new Error("Canvas is not supported"); } }; const createCanvasContext = (canvas) => { if (typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement) { return canvas.getContext("2d"); } else if (canvas instanceof OffscreenCanvas) { return canvas.getContext("2d"); } else { return null; } }; if (isHTMLImageEle) { const canvas = createCanvas(); canvas.width = image.width; canvas.height = image.height; const pixels2DContext = createCanvasContext(canvas); if (pixels2DContext != null) { let height = image.height; let width = image.width; if (options !== void 0 && options.resizedHeight !== void 0 && options.resizedWidth !== void 0) { height = options.resizedHeight; width = options.resizedWidth; } if (options !== void 0) { bufferToTensorOptions = options; if (options.tensorFormat !== void 0) { throw new Error("Image input config format must be RGBA for HTMLImageElement"); } else { bufferToTensorOptions.tensorFormat = "RGBA"; } bufferToTensorOptions.height = height; bufferToTensorOptions.width = width; } else { bufferToTensorOptions.tensorFormat = "RGBA"; bufferToTensorOptions.height = height; bufferToTensorOptions.width = width; } pixels2DContext.drawImage(image, 0, 0); data = pixels2DContext.getImageData(0, 0, width, height).data; } else { throw new Error("Can not access image data"); } } else if (isImageDataEle) { let height; let width; if (options !== void 0 && options.resizedWidth !== void 0 && options.resizedHeight !== void 0) { height = options.resizedHeight; width = options.resizedWidth; } else { height = image.height; width = image.width; } if (options !== void 0) { bufferToTensorOptions = options; } bufferToTensorOptions.format = "RGBA"; bufferToTensorOptions.height = height; bufferToTensorOptions.width = width; if (options !== void 0) { const tempCanvas = createCanvas(); tempCanvas.width = width; tempCanvas.height = height; const pixels2DContext = createCanvasContext(tempCanvas); if (pixels2DContext != null) { pixels2DContext.putImageData(image, 0, 0); data = pixels2DContext.getImageData(0, 0, width, height).data; } else { throw new Error("Can not access image data"); } } else { data = image.data; } } else if (isImageBitmap) { if (options === void 0) { throw new Error("Please provide image config with format for Imagebitmap"); } const canvas = createCanvas(); canvas.width = image.width; canvas.height = image.height; const pixels2DContext = createCanvasContext(canvas); if (pixels2DContext != null) { const height = image.height; const width = image.width; pixels2DContext.drawImage(image, 0, 0, width, height); data = pixels2DContext.getImageData(0, 0, width, height).data; bufferToTensorOptions.height = height; bufferToTensorOptions.width = width; return bufferToTensor(data, bufferToTensorOptions); } else { throw new Error("Can not access image data"); } } else if (isString) { return new Promise((resolve, reject) => { const canvas = createCanvas(); const context = createCanvasContext(canvas); if (!image || !context) { return reject(); } const newImage = new Image(); newImage.crossOrigin = "Anonymous"; newImage.src = image; newImage.onload = () => { canvas.width = newImage.width; canvas.height = newImage.height; context.drawImage(newImage, 0, 0, canvas.width, canvas.height); const img = context.getImageData(0, 0, canvas.width, canvas.height); bufferToTensorOptions.height = canvas.height; bufferToTensorOptions.width = canvas.width; resolve(bufferToTensor(img.data, bufferToTensorOptions)); }; }); } else { throw new Error("Input data provided is not supported - aborted tensor creation"); } if (data !== void 0) { return bufferToTensor(data, bufferToTensorOptions); } else { throw new Error("Input data provided is not supported - aborted tensor creation"); } }; tensorFromTexture = (texture, options) => { const { width, height, download, dispose } = options; const dims = [1, height, width, 4]; return new Tensor({ location: "texture", type: "float32", texture, dims, download, dispose }); }; tensorFromGpuBuffer = (gpuBuffer, options) => { const { dataType, dims, download, dispose } = options; return new Tensor({ location: "gpu-buffer", type: dataType ?? "float32", gpuBuffer, dims, download, dispose }); }; tensorFromMLTensor = (mlTensor, options) => { const { dataType, dims, download, dispose } = options; return new Tensor({ location: "ml-tensor", type: dataType ?? "float32", mlTensor, dims, download, dispose }); }; tensorFromPinnedBuffer = (type, buffer, dims) => new Tensor({ location: "cpu-pinned", type, data: buffer, dims: dims ?? [buffer.length] }); } }); // common/dist/esm/tensor-impl-type-mapping.js var NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP, NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP, isTypedArrayChecked, checkTypedArray; var init_tensor_impl_type_mapping = __esm({ "common/dist/esm/tensor-impl-type-mapping.js"() { "use strict"; NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = /* @__PURE__ */ new Map([ ["float32", Float32Array], ["uint8", Uint8Array], ["int8", Int8Array], ["uint16", Uint16Array], ["int16", Int16Array], ["int32", Int32Array], ["bool", Uint8Array], ["float64", Float64Array], ["uint32", Uint32Array], ["int4", Uint8Array], ["uint4", Uint8Array] ]); NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP = /* @__PURE__ */ new Map([ [Float32Array, "float32"], [Uint8Array, "uint8"], [Int8Array, "int8"], [Uint16Array, "uint16"], [Int16Array, "int16"], [Int32Array, "int32"], [Float64Array, "float64"], [Uint32Array, "uint32"] ]); isTypedArrayChecked = false; checkTypedArray = () => { if (!isTypedArrayChecked) { isTypedArrayChecked = true; const isBigInt64ArrayAvailable = typeof BigInt64Array !== "undefined" && BigInt64Array.from; const isBigUint64ArrayAvailable = typeof BigUint64Array !== "undefined" && BigUint64Array.from; const Float16Array2 = globalThis.Float16Array; const isFloat16ArrayAvailable = typeof Float16Array2 !== "undefined" && Float16Array2.from; if (isBigInt64ArrayAvailable) { NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set("int64", BigInt64Array); NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(BigInt64Array, "int64"); } if (isBigUint64ArrayAvailable) { NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set("uint64", BigUint64Array); NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(BigUint64Array, "uint64"); } if (isFloat16ArrayAvailable) { NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set("float16", Float16Array2); NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(Float16Array2, "float16"); } else { NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set("float16", Uint16Array); } } }; } }); // common/dist/esm/tensor-utils-impl.js var calculateSize, tensorReshape; var init_tensor_utils_impl = __esm({ "common/dist/esm/tensor-utils-impl.js"() { "use strict"; init_tensor_impl(); calculateSize = (dims) => { let size = 1; for (let i = 0; i < dims.length; i++) { const dim = dims[i]; if (typeof dim !== "number" || !Number.isSafeInteger(dim)) { throw new TypeError(`dims[${i}] must be an integer, got: ${dim}`); } if (dim < 0) { throw new RangeError(`dims[${i}] must be a non-negative integer, got: ${dim}`); } size *= dim; } return size; }; tensorReshape = (tensor, dims) => { switch (tensor.location) { case "cpu": return new Tensor(tensor.type, tensor.data, dims); case "cpu-pinned": return new Tensor({ location: "cpu-pinned", data: tensor.data, type: tensor.type, dims }); case "texture": return new Tensor({ location: "texture", texture: tensor.texture, type: tensor.type, dims }); case "gpu-buffer": return new Tensor({ location: "gpu-buffer", gpuBuffer: tensor.gpuBuffer, type: tensor.type, dims }); case "ml-tensor": return new Tensor({ location: "ml-tensor", mlTensor: tensor.mlTensor, type: tensor.type, dims }); default: throw new Error(`tensorReshape: tensor location ${tensor.location} is not supported`); } }; } }); // common/dist/esm/tensor-impl.js var Tensor; var init_tensor_impl = __esm({ "common/dist/esm/tensor-impl.js"() { "use strict"; init_tensor_conversion_impl(); init_tensor_factory_impl(); init_tensor_impl_type_mapping(); init_tensor_utils_impl(); Tensor = class { /** * implementation. */ constructor(arg0, arg1, arg2) { checkTypedArray(); let type; let dims; if (typeof arg0 === "object" && "location" in arg0) { this.dataLocation = arg0.location; type = arg0.type; dims = arg0.dims; switch (arg0.location) { case "cpu-pinned": { const expectedTypedArrayConstructor = NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.get(type); if (!expectedTypedArrayConstructor) { throw new TypeError(`unsupported type "${type}" to create tensor from pinned buffer`); } if (!(arg0.data instanceof expectedTypedArrayConstructor)) { throw new TypeError(`buffer should be of type ${expectedTypedArrayConstructor.name}`); } this.cpuData = arg0.data; break; } case "texture": { if (type !== "float32") { throw new TypeError(`unsupported type "${type}" to create tensor from texture`); } this.gpuTextureData = arg0.texture; this.downloader = arg0.download; this.disposer = arg0.dispose; break; } case "gpu-buffer": { if (type !== "float32" && type !== "float16" && type !== "int32" && type !== "int64" && type !== "uint32" && type !== "uint8" && type !== "bool" && type !== "uint4" && type !== "int4") { throw new TypeError(`unsupported type "${type}" to create tensor from gpu buffer`); } this.gpuBufferData = arg0.gpuBuffer; this.downloader = arg0.download; this.disposer = arg0.dispose; break; } case "ml-tensor": { if (type !== "float32" && type !== "float16" && type !== "int32" && type !== "int64" && type !== "uint32" && type !== "uint64" && type !== "int8" && type !== "uint8" && type !== "bool" && type !== "uint4" && type !== "int4") { throw new TypeError(`unsupported type "${type}" to create tensor from MLTensor`); } this.mlTensorData = arg0.mlTensor; this.downloader = arg0.download; this.disposer = arg0.dispose; break; } default: throw new Error(`Tensor constructor: unsupported location '${this.dataLocation}'`); } } else { let data; let maybeDims; if (typeof arg0 === "string") { type = arg0; maybeDims = arg2; if (arg0 === "string") { if (!Array.isArray(arg1)) { throw new TypeError("A string tensor's data must be a string array."); } data = arg1; } else { const typedArrayConstructor = NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.get(arg0); if (typedArrayConstructor === void 0) { throw new TypeError(`Unsupported tensor type: ${arg0}.`); } if (Array.isArray(arg1)) { if (arg0 === "float16" && typedArrayConstructor === Uint16Array || arg0 === "uint4" || arg0 === "int4") { throw new TypeError(`Creating a ${arg0} tensor from number array is not supported. Please use ${typedArrayConstructor.name} as data.`); } else if (arg0 === "uint64" || arg0 === "int64") { data = typedArrayConstructor.from(arg1, BigInt); } else { data = typedArrayConstructor.from(arg1); } } else if (arg1 instanceof typedArrayConstructor) { data = arg1; } else if (arg1 instanceof Uint8ClampedArray) { if (arg0 === "uint8") { data = Uint8Array.from(arg1); } else { throw new TypeError(`A Uint8ClampedArray tensor's data must be type of uint8`); } } else if (arg0 === "float16" && arg1 instanceof Uint16Array && typedArrayConstructor !== Uint16Array) { data = new globalThis.Float16Array(arg1.buffer, arg1.byteOffset, arg1.length); } else { throw new TypeError(`A ${type} tensor's data must be type of ${typedArrayConstructor}`); } } } else { maybeDims = arg1; if (Array.isArray(arg0)) { if (arg0.length === 0) { throw new TypeError("Tensor type cannot be inferred from an empty array."); } const firstElementType = typeof arg0[0]; if (firstElementType === "string") { type = "string"; data = arg0; } else if (firstElementType === "boolean") { type = "bool"; data = Uint8Array.from(arg0); } else { throw new TypeError(`Invalid element type of data array: ${firstElementType}.`); } } else if (arg0 instanceof Uint8ClampedArray) { type = "uint8"; data = Uint8Array.from(arg0); } else { const mappedType = NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.get(arg0.constructor); if (mappedType === void 0) { throw new TypeError(`Unsupported type for tensor data: ${arg0.constructor}.`); } type = mappedType; data = arg0; } } if (maybeDims === void 0) { maybeDims = [data.length]; } else if (!Array.isArray(maybeDims)) { throw new TypeError("A tensor's dims must be a number array"); } dims = maybeDims; this.cpuData = data; this.dataLocation = "cpu"; } const size = calculateSize(dims); if (this.cpuData && size !== this.cpuData.length) { if ((type === "uint4" || type === "int4") && Math.ceil(size / 2) === this.cpuData.length) { } else { throw new Error(`Tensor's size(${size}) does not match data length(${this.cpuData.length}).`); } } this.type = type; this.dims = dims; this.size = size; } // #endregion // #region factory static async fromImage(image, options) { return tensorFromImage(image, options); } static fromTexture(texture, options) { return tensorFromTexture(texture, options); } static fromGpuBuffer(gpuBuffer, options) { return tensorFromGpuBuffer(gpuBuffer, options); } static fromMLTensor(mlTensor, options) { return tensorFromMLTensor(mlTensor, options); } static fromPinnedBuffer(type, buffer, dims) { return tensorFromPinnedBuffer(type, buffer, dims); } // #endregion // #region conversions toDataURL(options) { return tensorToDataURL(this, options); } toImageData(options) { return tensorToImageData(this, options); } // #endregion // #region properties get data() { this.ensureValid(); if (!this.cpuData) { throw new Error("The data is not on CPU. Use `getData()` to download GPU data to CPU, or use `texture` or `gpuBuffer` property to access the GPU data directly."); } return this.cpuData; } get location() { return this.dataLocation; } get texture() { this.ensureValid(); if (!this.gpuTextureData) { throw new Error("The data is not stored as a WebGL texture."); } return this.gpuTextureData; } get gpuBuffer() { this.ensureValid(); if (!this.gpuBufferData) { throw new Error("The data is not stored as a WebGPU buffer."); } return this.gpuBufferData; } get mlTensor() { this.ensureValid(); if (!this.mlTensorData) { throw new Error("The data is not stored as a WebNN MLTensor."); } return this.mlTensorData; } // #endregion // #region methods async getData(releaseData) { this.ensureValid(); switch (this.dataLocation) { case "cpu": case "cpu-pinned": return this.data; case "texture": case "gpu-buffer": case "ml-tensor": { if (!this.downloader) { throw new Error("The current tensor is not created with a specified data downloader."); } if (this.isDownloading) { throw new Error("The current tensor is being downloaded."); } try { this.isDownloading = true; const data = await this.downloader(); this.downloader = void 0; this.dataLocation = "cpu"; this.cpuData = data; if (releaseData && this.disposer) { this.disposer(); this.disposer = void 0; } return data; } finally { this.isDownloading = false; } } default: throw new Error(`cannot get data from location: ${this.dataLocation}`); } } dispose() { if (this.isDownloading) { throw new Error("The current tensor is being downloaded."); } if (this.disposer) { this.disposer(); this.disposer = void 0; } this.cpuData = void 0; this.gpuTextureData = void 0; this.gpuBufferData = void 0; this.mlTensorData = void 0; this.downloader = void 0; this.isDownloading = void 0; this.dataLocation = "none"; } // #endregion // #region tensor utilities ensureValid() { if (this.dataLocation === "none") { throw new Error("The tensor is disposed."); } } reshape(dims) { this.ensureValid(); if (this.downloader || this.disposer) { throw new Error("Cannot reshape a tensor that owns GPU resource."); } return tensorReshape(this, dims); } }; } }); // common/dist/esm/tensor.js var Tensor2; var init_tensor = __esm({ "common/dist/esm/tensor.js"() { "use strict"; init_tensor_impl(); Tensor2 = Tensor; } }); // common/dist/esm/trace.js var TRACE, TRACE_FUNC, TRACE_FUNC_BEGIN, TRACE_FUNC_END; var init_trace = __esm({ "common/dist/esm/trace.js"() { "use strict"; init_env_impl(); TRACE = (deviceType, label) => { if (typeof env.trace === "undefined" ? !env.wasm.trace : !env.trace) { return; } console.timeStamp(`${deviceType}::ORT::${label}`); }; TRACE_FUNC = (msg, extraMsg) => { const stack = new Error().stack?.split(/\r\n|\r|\n/g) || []; let hasTraceFunc = false; for (let i = 0; i < stack.length; i++) { if (hasTraceFunc && !stack[i].includes("TRACE_FUNC")) { let label = `FUNC_${msg}::${stack[i].trim().split(" ")[1]}`; if (extraMsg) { label += `::${extraMsg}`; } TRACE("CPU", label); return; } if (stack[i].includes("TRACE_FUNC")) { hasTraceFunc = true; } } }; TRACE_FUNC_BEGIN = (extraMsg) => { if (typeof env.trace === "undefined" ? !env.wasm.trace : !env.trace) { return; } TRACE_FUNC("BEGIN", extraMsg); }; TRACE_FUNC_END = (extraMsg) => { if (typeof env.trace === "undefined" ? !env.wasm.trace : !env.trace) { return; } TRACE_FUNC("END", extraMsg); }; } }); // common/dist/esm/inference-session-impl.js var InferenceSession; var init_inference_session_impl = __esm({ "common/dist/esm/inference-session-impl.js"() { "use strict"; init_backend_impl(); init_tensor(); init_trace(); InferenceSession = class _InferenceSession { constructor(handler) { this.handler = handler; } async run(feeds, arg1, arg2) { TRACE_FUNC_BEGIN(); 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; } }; } }); // common/dist/esm/inference-session.js var InferenceSession2; var init_inference_session = __esm({ "common/dist/esm/inference-session.js"() { "use strict"; init_inference_session_impl(); InferenceSession2 = InferenceSession; } }); // common/dist/esm/tensor-conversion.js var init_tensor_conversion = __esm({ "common/dist/esm/tensor-conversion.js"() { "use strict"; } }); // common/dist/esm/tensor-factory.js var init_tensor_factory = __esm({ "common/dist/esm/tensor-factory.js"() { "use strict"; } }); // common/dist/esm/onnx-model.js var init_onnx_model = __esm({ "common/dist/esm/onnx-model.js"() { "use strict"; } }); // common/dist/esm/onnx-value.js var init_onnx_value = __esm({ "common/dist/esm/onnx-value.js"() { "use strict"; } }); // common/dist/esm/index.js var esm_exports = {}; __export(esm_exports, { InferenceSession: () => InferenceSession2, TRACE: () => TRACE, TRACE_FUNC_BEGIN: () => TRACE_FUNC_BEGIN, TRACE_FUNC_END: () => TRACE_FUNC_END, Tensor: () => Tensor2, env: () => env2, registerBackend: () => registerBackend }); var init_esm = __esm({ "common/dist/esm/index.js"() { "use strict"; init_backend(); init_env(); init_inference_session(); init_tensor(); init_tensor_conversion(); init_tensor_factory(); init_trace(); init_onnx_model(); init_onnx_value(); } }); // web/lib/wasm/wasm-utils-env.ts var isNode; var init_wasm_utils_env = __esm({ "web/lib/wasm/wasm-utils-env.ts"() { "use strict"; isNode = false; } }); // web/lib/wasm/proxy-worker/main.ts var main_exports = {}; __export(main_exports, { default: () => main_default }); var WORKER_NAME, isProxyWorker, main_default; var init_main = __esm({ "web/lib/wasm/proxy-worker/main.ts"() { "use strict"; init_wasm_core_impl(); init_wasm_factory(); init_wasm_utils_import(); WORKER_NAME = "ort-wasm-proxy-worker"; isProxyWorker = globalThis.self?.name === WORKER_NAME; if (isProxyWorker) { self.onmessage = (ev) => { const { type, in: message } = ev.data; try { switch (type) { case "init-wasm": initializeWebAssembly(message.wasm).then( () => { initRuntime(message).then( () => { postMessage({ type }); }, (err) => { postMessage({ type, err }); } ); }, (err) => { postMessage({ type, err }); } ); break; case "init-ep": { const { epName, env: env3 } = message; initEp(env3, epName).then( () => { postMessage({ type }); }, (err) => { postMessage({ type, err }); } ); break; } case "copy-from": { const { buffer } = message; const bufferData = copyFromExternalBuffer(buffer); postMessage({ type, out: bufferData }); break; } case "create": { const { model, options } = message; createSession(model, options).then( (sessionMetadata) => { postMessage({ type, out: sessionMetadata }); }, (err) => { postMessage({ type, err }); } ); break; } case "release": releaseSession(message); postMessage({ type }); break; case "run": { const { sessionId, inputIndices, inputs, outputIndices, options } = message; run(sessionId, inputIndices, inputs, outputIndices, new Array(outputIndices.length).fill(null), options).then( (outputs) => { if (outputs.some((o) => o[3] !== "cpu")) { postMessage({ type, err: "Proxy does not support non-cpu tensor location." }); } else { postMessage( { type, out: outputs }, extractTransferableBuffers([...inputs, ...outputs]) ); } }, (err) => { postMessage({ type, err }); } ); break; } case "end-profiling": endProfiling(message); postMessage({ type }); break; default: } } catch (err) { postMessage({ type, err }); } }; } main_default = isProxyWorker ? null : (urlOverride) => new Worker(urlOverride ?? scriptSrc, { type: false ? "module" : "classic", name: WORKER_NAME }); } }); // web/lib/wasm/wasm-utils-import.ts var origin, getScriptSrc, scriptSrc, inferWasmPathPrefixFromScriptSrc, isSameOrigin, normalizeUrl, fallbackUrl, preload, dynamicImportDefault, createProxyWorker, importProxyWorker, embeddedWasmModule, importWasmModule; var init_wasm_utils_import = __esm({ "web/lib/wasm/wasm-utils-import.ts"() { "use strict"; init_wasm_utils_env(); origin = isNode || typeof location === "undefined" ? void 0 : location.origin; getScriptSrc = () => { if (isNode) { return void 0; } if (false) { if (isEsmImportMetaUrlHardcodedAsFileUri) { const URL2 = URL; return new URL(new URL2("ort.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, calcDataOffsetSnippet, updateElementsSnippet, 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.`); } }; calcDataOffsetSnippet = (dataRank, parallel) => `${dataRank === 1 ? ` let element_count_dim = uniforms.output_strides; let dim_value = uniforms.output_shape;` : ` let element_count_dim = uniforms.output_strides[${parallel ? "i - indices_start" : "i"}]; let dim_value = uniforms.output_shape[${parallel ? "i - indices_start" : "i"} + uniforms.last_index_dimension];`} 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));`; updateElementsSnippet = (attributes, outputTypeValue, parallel) => `for (var i = 0u; i < uniforms.num_updates_elements; i++) { let value = updates[uniforms.num_updates_elements * ${parallel ? "global_idx" : "idx"} + i]; ${atomicReductionSnippet(attributes.reduction, "output[data_offset + i]", "value", outputTypeValue)} }`; createScatterNDProgramInfo = (inputs, attributes) => { const inputShape = inputs[0].dims; const indicesShape = inputs[1].dims; const outputShape = inputShape; const components = 1; const outputSize = Math.ceil(ShapeUtil.size(indicesShape) / components); const lastIndexDimension = indicesShape[indicesShape.length - 1]; const numUpdatesElements = ShapeUtil.sizeFromDimension(inputShape, lastIndexDimension); const numIndicesElements = ShapeUtil.sizeFromDimension(indicesShape, 0) / 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 hasDuplicates = false; if (${attributes.reduction === "none"}) { for (var i = 0; i < ${numIndicesElements}; i = i + 1) { for (var j = i + 1; j < ${numIndicesElements}; j = j + 1) { var index_i = i32(indices[i].x); var index_j = i32(indices[j].x); if (index_i == index_j) { hasDuplicates = true; break; } } if (hasDuplicates) { break; } } } if (${attributes.reduction === "none"} && hasDuplicates) { if (global_idx != 0u) { return; } // Process each index-update pair individually when duplicates exist for (var idx = 0u; idx < ${numIndicesElements}u; idx++) { var data_offset = 0u; for (var i = 0u; i < uniforms.last_index_dimension; i++) { var index = i32(indices[idx * uniforms.last_index_dimension + i].x); ${calcDataOffsetSnippet(inputShape.length, false)} } ${updateElementsSnippet(attributes, output.type.value, false)} } return; } var data_offset = 0u; var indices_start = uniforms.last_index_dimension * global_idx; var indices_end = indices_start + uniforms.last_index_dimension; for (var i = indices_start; i < indices_end; i++) { var index = i32(indices[i].x); ${calcDataOffsetSnippet(inputShape.length, true)} } ${updateElementsSnippet(attributes, output.type.value, true)} }`; }; 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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vY29tbW9uL2xpYi9iYWNrZW5kLWltcGwudHMiLCAiLi4vLi4vY29tbW9uL2xpYi9iYWNrZW5kLnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvdmVyc2lvbi50cyIsICIuLi8uLi9jb21tb24vbGliL2Vudi1pbXBsLnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvZW52LnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvdGVuc29yLWNvbnZlcnNpb24taW1wbC50cyIsICIuLi8uLi9jb21tb24vbGliL3RlbnNvci1mYWN0b3J5LWltcGwudHMiLCAiLi4vLi4vY29tbW9uL2xpYi90ZW5zb3ItaW1wbC10eXBlLW1hcHBpbmcudHMiLCAiLi4vLi4vY29tbW9uL2xpYi90ZW5zb3ItdXRpbHMtaW1wbC50cyIsICIuLi8uLi9jb21tb24vbGliL3RlbnNvci1pbXBsLnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvdGVuc29yLnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvdHJhY2UudHMiLCAiLi4vLi4vY29tbW9uL2xpYi9pbmZlcmVuY2Utc2Vzc2lvbi1pbXBsLnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvaW5mZXJlbmNlLXNlc3Npb24udHMiLCAiLi4vLi4vY29tbW9uL2xpYi90ZW5zb3ItY29udmVyc2lvbi50cyIsICIuLi8uLi9jb21tb24vbGliL3RlbnNvci1mYWN0b3J5LnRzIiwgIi4uLy4uL2NvbW1vbi9saWIvb25ueC1tb2RlbC50cyIsICIuLi8uLi9jb21tb24vbGliL29ubngtdmFsdWUudHMiLCAiLi4vLi4vY29tbW9uL2xpYi9pbmRleC50cyIsICIuLi9saWIvd2FzbS93YXNtLXV0aWxzLWVudi50cyIsICIuLi9saWIvd2FzbS9wcm94eS13b3JrZXIvbWFpbi50cyIsICIuLi9saWIvd2FzbS93YXNtLXV0aWxzLWltcG9ydC50cyIsICIuLi9saWIvd2FzbS93YXNtLWZhY3RvcnkudHMiLCAiLi4vbGliL3dhc20vd2FzbS11dGlscy50cyIsICIuLi9saWIvd2FzbS9ydW4tb3B0aW9ucy50cyIsICIuLi9saWIvd2FzbS9zZXNzaW9uLW9wdGlvbnMudHMiLCAiLi4vbGliL3dhc20vd2FzbS1jb21tb24udHMiLCAiLi4vbGliL3dhc20vd2FzbS11dGlscy1sb2FkLWZpbGUudHMiLCAiLi4vbGliL3dhc20vanNlcC9sb2cudHMiLCAiLi4vbGliL3dhc20vanNlcC91dGlsLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvdGVuc29yLXZpZXcudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJubi90ZW5zb3ItbWFuYWdlci50cyIsICIuLi9saWIvd2FzbS9qc2VwL2JhY2tlbmQtd2Vibm4udHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvdHlwZXMudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvZ3B1LWRhdGEtbWFuYWdlci50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXkudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2NvbW1vbi50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvdHJhbnNwb3NlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9yZWR1Y2Utc2hhcmVkLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9yZWR1Y2UudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2FyZ21pbm1heC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvYXR0ZW50aW9uLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9iYXRjaC1ub3JtLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9iaWFzLWFkZC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvdW5hcnktb3AudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2JpYXMtc3BsaXQtZ2VsdS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvYmluYXJ5LW9wLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9jb25jYXQudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2Z1c2UtdXRpbHMudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzLzNyZC1wYXJ0eS9hY3RpdmF0aW9uX3V0aWwudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzLzNyZC1wYXJ0eS9jb252X3V0aWwudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL21hdG11bC1zaGFkZXJzLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy8zcmQtcGFydHkvbWF0bXVsX3BhY2tlZF93ZWJncHUudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzLzNyZC1wYXJ0eS9jb252MmRfbW1fd2ViZ3B1LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy8zcmQtcGFydHkvY29udjNkX25haXZlX3dlYmdwdS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvY29udi1ncm91cGVkLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9jb252LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy8zcmQtcGFydHkvY29udl9iYWNrcHJvcF93ZWJncHUudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2NvbnYtdHJhbnNwb3NlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9jdW1zdW0udHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2RlcHRoLXRvLXNwYWNlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9laW5zdW0udHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2V4cGFuZC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvZmFzdC1nZWx1LnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9nYXRoZXIudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2dhdGhlci1uZC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvZ2F0aGVyLWJsb2NrLXF1YW50aXplZC50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvZ2F0aGVyLWVsZW1lbnRzLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9nZW1tLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9ncmlkLXNhbXBsZS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvbXVsdGloZWFkLWF0dGVudGlvbi50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvc3BsaXQudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3JvdGFyeS1lbWJlZGRpbmcudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2dyb3VwLXF1ZXJ5LWF0dGVudGlvbi50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvaW5zdGFuY2Utbm9ybS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvbGF5ZXItbm9ybS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvbWF0bXVsLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9tYXRtdWxuYml0cy50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvcGFkLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9wb29sLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9xdWFudGl6ZS1saW5lYXIudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3JhbmdlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9zY2F0dGVyLW5kLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9yZXNpemUudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3NraXAtbGF5ZXItbm9ybS50cyIsICIuLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvc2xpY2UudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3NvZnRtYXgudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3RpbGUudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL3doZXJlLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wLXJlc29sdmUtcnVsZXMudHMiLCAiLi4vbGliL3dhc20vanNlcC93ZWJncHUvcHJvZ3JhbS1tYW5hZ2VyLnRzIiwgIi4uL2xpYi93YXNtL2pzZXAvYmFja2VuZC13ZWJncHUudHMiLCAiLi4vbGliL3dhc20vanNlcC9pbml0LnRzIiwgIi4uL2xpYi93YXNtL3dhc20tY29yZS1pbXBsLnRzIiwgIi4uL2xpYi93YXNtL3Byb3h5LXdyYXBwZXIudHMiLCAiLi4vbGliL3dhc20vc2Vzc2lvbi1oYW5kbGVyLWluZmVyZW5jZS50cyIsICIuLi9saWIvYmFja2VuZC13YXNtLnRzIiwgIi4uL2xpYi9pbmRleC50cyIsICIuLi9saWIvdmVyc2lvbi50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IEJhY2tlbmQgfSBmcm9tICcuL2JhY2tlbmQuanMnO1xuaW1wb3J0IHsgSW5mZXJlbmNlU2Vzc2lvbiB9IGZyb20gJy4vaW5mZXJlbmNlLXNlc3Npb24uanMnO1xuXG5pbnRlcmZhY2UgQmFja2VuZEluZm8ge1xuICBiYWNrZW5kOiBCYWNrZW5kO1xuICBwcmlvcml0eTogbnVtYmVyO1xuXG4gIGluaXRQcm9taXNlPzogUHJvbWlzZTx2b2lkPjtcbiAgaW5pdGlhbGl6ZWQ/OiBib29sZWFuO1xuICBhYm9ydGVkPzogYm9vbGVhbjtcbiAgZXJyb3I/OiBzdHJpbmc7XG59XG5cbmNvbnN0IGJhY2tlbmRzOiBNYXA8c3RyaW5nLCBCYWNrZW5kSW5mbz4gPSBuZXcgTWFwKCk7XG5jb25zdCBiYWNrZW5kc1NvcnRlZEJ5UHJpb3JpdHk6IHN0cmluZ1tdID0gW107XG5cbi8qKlxuICogUmVnaXN0ZXIgYSBiYWNrZW5kLlxuICpcbiAqIEBwYXJhbSBuYW1lIC0gdGhlIG5hbWUgYXMgYSBrZXkgdG8gbG9va3VwIGFzIGFuIGV4ZWN1dGlvbiBwcm92aWRlci5cbiAqIEBwYXJhbSBiYWNrZW5kIC0gdGhlIGJhY2tlbmQgb2JqZWN0LlxuICogQHBhcmFtIHByaW9yaXR5IC0gYW4gaW50ZWdlciBpbmRpY2F0aW5nIHRoZSBwcmlvcml0eSBvZiB0aGUgYmFja2VuZC4gSGlnaGVyIG51bWJlciBtZWFucyBoaWdoZXIgcHJpb3JpdHkuIGlmIHByaW9yaXR5XG4gKiA8IDAsIGl0IHdpbGwgYmUgY29uc2lkZXJlZCBhcyBhICdiZXRhJyB2ZXJzaW9uIGFuZCB3aWxsIG5vdCBiZSB1c2VkIGFzIGEgZmFsbGJhY2sgYmFja2VuZCBieSBkZWZhdWx0LlxuICpcbiAqIEBpZ25vcmVcbiAqL1xuZXhwb3J0IGNvbnN0IHJlZ2lzdGVyQmFja2VuZCA9IChuYW1lOiBzdHJpbmcsIGJhY2tlbmQ6IEJhY2tlbmQsIHByaW9yaXR5OiBudW1iZXIpOiB2b2lkID0+IHtcbiAgaWYgKGJhY2tlbmQgJiYgdHlwZW9mIGJhY2tlbmQuaW5pdCA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgYmFja2VuZC5jcmVhdGVJbmZlcmVuY2VTZXNzaW9uSGFuZGxlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGNvbnN0IGN1cnJlbnRCYWNrZW5kID0gYmFja2VuZHMuZ2V0KG5hbWUpO1xuICAgIGlmIChjdXJyZW50QmFja2VuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBiYWNrZW5kcy5zZXQobmFtZSwgeyBiYWNrZW5kLCBwcmlvcml0eSB9KTtcbiAgICB9IGVsc2UgaWYgKGN1cnJlbnRCYWNrZW5kLnByaW9yaXR5ID4gcHJpb3JpdHkpIHtcbiAgICAgIC8vIHNhbWUgbmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgd2l0aCBhIGhpZ2hlciBwcmlvcml0eS4gc2tpcCByZWdpc3RlcmF0aW9uLlxuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSBpZiAoY3VycmVudEJhY2tlbmQucHJpb3JpdHkgPT09IHByaW9yaXR5KSB7XG4gICAgICBpZiAoY3VycmVudEJhY2tlbmQuYmFja2VuZCAhPT0gYmFja2VuZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCByZWdpc3RlciBiYWNrZW5kIFwiJHtuYW1lfVwiIHVzaW5nIHByaW9yaXR5ICR7cHJpb3JpdHl9YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHByaW9yaXR5ID49IDApIHtcbiAgICAgIGNvbnN0IGkgPSBiYWNrZW5kc1NvcnRlZEJ5UHJpb3JpdHkuaW5kZXhPZihuYW1lKTtcbiAgICAgIGlmIChpICE9PSAtMSkge1xuICAgICAgICBiYWNrZW5kc1NvcnRlZEJ5UHJpb3JpdHkuc3BsaWNlKGksIDEpO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoYmFja2VuZHMuZ2V0KGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eVtpXSkhLnByaW9yaXR5IDw9IHByaW9yaXR5KSB7XG4gICAgICAgICAgYmFja2VuZHNTb3J0ZWRCeVByaW9yaXR5LnNwbGljZShpLCAwLCBuYW1lKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eS5wdXNoKG5hbWUpO1xuICAgIH1cbiAgICByZXR1cm47XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZUVycm9yKCdub3QgYSB2YWxpZCBiYWNrZW5kJyk7XG59O1xuXG4vKipcbiAqIFRyeSB0byByZXNvbHZlIGFuZCBpbml0aWFsaXplIGEgYmFja2VuZC5cbiAqXG4gKiBAcGFyYW0gYmFja2VuZE5hbWUgLSB0aGUgbmFtZSBvZiB0aGUgYmFja2VuZC5cbiAqIEByZXR1cm5zIHRoZSBiYWNrZW5kIGluc3RhbmNlIGlmIHJlc29sdmVkIGFuZCBpbml0aWFsaXplZCBzdWNjZXNzZnVsbHksIG9yIGFuIGVycm9yIG1lc3NhZ2UgaWYgZmFpbGVkLlxuICovXG5jb25zdCB0cnlSZXNvbHZlQW5kSW5pdGlhbGl6ZUJhY2tlbmQgPSBhc3luYyAoYmFja2VuZE5hbWU6IHN0cmluZyk6IFByb21pc2U8QmFja2VuZCB8IHN0cmluZz4gPT4ge1xuICBjb25zdCBiYWNrZW5kSW5mbyA9IGJhY2tlbmRzLmdldChiYWNrZW5kTmFtZSk7XG4gIGlmICghYmFja2VuZEluZm8pIHtcbiAgICByZXR1cm4gJ2JhY2tlbmQgbm90IGZvdW5kLic7XG4gIH1cblxuICBpZiAoYmFja2VuZEluZm8uaW5pdGlhbGl6ZWQpIHtcbiAgICByZXR1cm4gYmFja2VuZEluZm8uYmFja2VuZDtcbiAgfSBlbHNlIGlmIChiYWNrZW5kSW5mby5hYm9ydGVkKSB7XG4gICAgcmV0dXJuIGJhY2tlbmRJbmZvLmVycm9yITtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBpc0luaXRpYWxpemluZyA9ICEhYmFja2VuZEluZm8uaW5pdFByb21pc2U7XG4gICAgdHJ5IHtcbiAgICAgIGlmICghaXNJbml0aWFsaXppbmcpIHtcbiAgICAgICAgYmFja2VuZEluZm8uaW5pdFByb21pc2UgPSBiYWNrZW5kSW5mby5iYWNrZW5kLmluaXQoYmFja2VuZE5hbWUpO1xuICAgICAgfVxuICAgICAgYXdhaXQgYmFja2VuZEluZm8uaW5pdFByb21pc2U7XG4gICAgICBiYWNrZW5kSW5mby5pbml0aWFsaXplZCA9IHRydWU7XG4gICAgICByZXR1cm4gYmFja2VuZEluZm8uYmFja2VuZDtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIWlzSW5pdGlhbGl6aW5nKSB7XG4gICAgICAgIGJhY2tlbmRJbmZvLmVycm9yID0gYCR7ZX1gO1xuICAgICAgICBiYWNrZW5kSW5mby5hYm9ydGVkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYWNrZW5kSW5mby5lcnJvciE7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGRlbGV0ZSBiYWNrZW5kSW5mby5pbml0UHJvbWlzZTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogUmVzb2x2ZSBleGVjdXRpb24gcHJvdmlkZXJzIGZyb20gdGhlIHNwZWNpZmljIHNlc3Npb24gb3B0aW9ucy5cbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyAtIHRoZSBzZXNzaW9uIG9wdGlvbnMgb2JqZWN0LlxuICogQHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSB0dXBsZSBvZiBhbiBpbml0aWFsaXplZCBiYWNrZW5kIGluc3RhbmNlIGFuZCBhIHNlc3Npb24gb3B0aW9ucyBvYmplY3Qgd2l0aFxuICogZmlsdGVyZWQgRVAgbGlzdC5cbiAqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBjb25zdCByZXNvbHZlQmFja2VuZEFuZEV4ZWN1dGlvblByb3ZpZGVycyA9IGFzeW5jIChcbiAgb3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyxcbik6IFByb21pc2U8W2JhY2tlbmQ6IEJhY2tlbmQsIG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnNdPiA9PiB7XG4gIC8vIGV4dHJhY3QgYmFja2VuZCBoaW50cyBmcm9tIHNlc3Npb24gb3B0aW9uc1xuICBjb25zdCBlcHMgPSBvcHRpb25zLmV4ZWN1dGlvblByb3ZpZGVycyB8fCBbXTtcbiAgY29uc3QgYmFja2VuZEhpbnRzID0gZXBzLm1hcCgoaSkgPT4gKHR5cGVvZiBpID09PSAnc3RyaW5nJyA/IGkgOiBpLm5hbWUpKTtcbiAgY29uc3QgYmFja2VuZE5hbWVzID0gYmFja2VuZEhpbnRzLmxlbmd0aCA9PT0gMCA/IGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eSA6IGJhY2tlbmRIaW50cztcblxuICAvLyB0cnkgdG8gcmVzb2x2ZSBhbmQgaW5pdGlhbGl6ZSBhbGwgcmVxdWVzdGVkIGJhY2tlbmRzXG4gIGxldCBiYWNrZW5kOiBCYWNrZW5kIHwgdW5kZWZpbmVkO1xuICBjb25zdCBlcnJvcnMgPSBbXTtcbiAgY29uc3QgYXZhaWxhYmxlQmFja2VuZE5hbWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGZvciAoY29uc3QgYmFja2VuZE5hbWUgb2YgYmFja2VuZE5hbWVzKSB7XG4gICAgY29uc3QgcmVzb2x2ZVJlc3VsdCA9IGF3YWl0IHRyeVJlc29sdmVBbmRJbml0aWFsaXplQmFja2VuZChiYWNrZW5kTmFtZSk7XG4gICAgaWYgKHR5cGVvZiByZXNvbHZlUmVzdWx0ID09PSAnc3RyaW5nJykge1xuICAgICAgZXJyb3JzLnB1c2goeyBuYW1lOiBiYWNrZW5kTmFtZSwgZXJyOiByZXNvbHZlUmVzdWx0IH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIWJhY2tlbmQpIHtcbiAgICAgICAgYmFja2VuZCA9IHJlc29sdmVSZXN1bHQ7XG4gICAgICB9XG4gICAgICBpZiAoYmFja2VuZCA9PT0gcmVzb2x2ZVJlc3VsdCkge1xuICAgICAgICBhdmFpbGFibGVCYWNrZW5kTmFtZXMuYWRkKGJhY2tlbmROYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBpZiBubyBiYWNrZW5kIGlzIGF2YWlsYWJsZSwgdGhyb3cgZXJyb3IuXG4gIGlmICghYmFja2VuZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgbm8gYXZhaWxhYmxlIGJhY2tlbmQgZm91bmQuIEVSUjogJHtlcnJvcnMubWFwKChlKSA9PiBgWyR7ZS5uYW1lfV0gJHtlLmVycn1gKS5qb2luKCcsICcpfWApO1xuICB9XG5cbiAgLy8gZm9yIGVhY2ggZXhwbGljaXRseSByZXF1ZXN0ZWQgYmFja2VuZCwgaWYgaXQncyBub3QgYXZhaWxhYmxlLCBvdXRwdXQgd2FybmluZyBtZXNzYWdlLlxuICBmb3IgKGNvbnN0IHsgbmFtZSwgZXJyIH0gb2YgZXJyb3JzKSB7XG4gICAgaWYgKGJhY2tlbmRIaW50cy5pbmNsdWRlcyhuYW1lKSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYHJlbW92aW5nIHJlcXVlc3RlZCBleGVjdXRpb24gcHJvdmlkZXIgXCIke25hbWV9XCIgZnJvbSBzZXNzaW9uIG9wdGlvbnMgYmVjYXVzZSBpdCBpcyBub3QgYXZhaWxhYmxlOiAke2Vycn1gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBmaWx0ZXJlZEVwcyA9IGVwcy5maWx0ZXIoKGkpID0+IGF2YWlsYWJsZUJhY2tlbmROYW1lcy5oYXModHlwZW9mIGkgPT09ICdzdHJpbmcnID8gaSA6IGkubmFtZSkpO1xuXG4gIHJldHVybiBbXG4gICAgYmFja2VuZCxcbiAgICBuZXcgUHJveHkob3B0aW9ucywge1xuICAgICAgZ2V0OiAodGFyZ2V0LCBwcm9wKSA9PiB7XG4gICAgICAgIGlmIChwcm9wID09PSAnZXhlY3V0aW9uUHJvdmlkZXJzJykge1xuICAgICAgICAgIHJldHVybiBmaWx0ZXJlZEVwcztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUmVmbGVjdC5nZXQodGFyZ2V0LCBwcm9wKTtcbiAgICAgIH0sXG4gICAgfSksXG4gIF07XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBJbmZlcmVuY2VTZXNzaW9uIH0gZnJvbSAnLi9pbmZlcmVuY2Utc2Vzc2lvbi5qcyc7XG5pbXBvcnQgeyBPbm54VmFsdWUgfSBmcm9tICcuL29ubngtdmFsdWUuanMnO1xuXG4vKipcbiAqIEBpZ25vcmVcbiAqL1xuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIFNlc3Npb25IYW5kbGVyIHtcbiAgdHlwZSBGZWVkc1R5cGUgPSB7IFtuYW1lOiBzdHJpbmddOiBPbm54VmFsdWUgfTtcbiAgdHlwZSBGZXRjaGVzVHlwZSA9IHsgW25hbWU6IHN0cmluZ106IE9ubnhWYWx1ZSB8IG51bGwgfTtcbiAgdHlwZSBSZXR1cm5UeXBlID0geyBbbmFtZTogc3RyaW5nXTogT25ueFZhbHVlIH07XG59XG5cbi8qKlxuICogUmVwcmVzZW50cyBzaGFyZWQgU2Vzc2lvbkhhbmRsZXIgZnVuY3Rpb25hbGl0eVxuICpcbiAqIEBpZ25vcmVcbiAqL1xuaW50ZXJmYWNlIFNlc3Npb25IYW5kbGVyIHtcbiAgZGlzcG9zZSgpOiBQcm9taXNlPHZvaWQ+O1xuXG4gIHJlYWRvbmx5IGlucHV0TmFtZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuICByZWFkb25seSBvdXRwdXROYW1lczogcmVhZG9ubHkgc3RyaW5nW107XG5cbiAgcmVhZG9ubHkgaW5wdXRNZXRhZGF0YTogcmVhZG9ubHkgSW5mZXJlbmNlU2Vzc2lvbi5WYWx1ZU1ldGFkYXRhW107XG4gIHJlYWRvbmx5IG91dHB1dE1ldGFkYXRhOiByZWFkb25seSBJbmZlcmVuY2VTZXNzaW9uLlZhbHVlTWV0YWRhdGFbXTtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnQgYSBoYW5kbGVyIGluc3RhbmNlIG9mIGFuIGluZmVyZW5jZSBzZXNzaW9uLlxuICpcbiAqIEBpZ25vcmVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbmZlcmVuY2VTZXNzaW9uSGFuZGxlciBleHRlbmRzIFNlc3Npb25IYW5kbGVyIHtcbiAgc3RhcnRQcm9maWxpbmcoKTogdm9pZDtcbiAgZW5kUHJvZmlsaW5nKCk6IHZvaWQ7XG5cbiAgcnVuKFxuICAgIGZlZWRzOiBTZXNzaW9uSGFuZGxlci5GZWVkc1R5cGUsXG4gICAgZmV0Y2hlczogU2Vzc2lvbkhhbmRsZXIuRmV0Y2hlc1R5cGUsXG4gICAgb3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5SdW5PcHRpb25zLFxuICApOiBQcm9taXNlPFNlc3Npb25IYW5kbGVyLlJldHVyblR5cGU+O1xufVxuXG4vKipcbiAqIFJlcHJlc2VudCBhIGJhY2tlbmQgdGhhdCBwcm92aWRlcyBpbXBsZW1lbnRhdGlvbiBvZiBtb2RlbCBpbmZlcmVuY2luZy5cbiAqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmFja2VuZCB7XG4gIC8qKlxuICAgKiBJbml0aWFsaXplIHRoZSBiYWNrZW5kIGFzeW5jaHJvbm91c2x5LiBTaG91bGQgdGhyb3cgd2hlbiBmYWlsZWQuXG4gICAqL1xuICBpbml0KGJhY2tlbmROYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+O1xuXG4gIGNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKFxuICAgIHVyaU9yQnVmZmVyOiBzdHJpbmcgfCBVaW50OEFycmF5LFxuICAgIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zLFxuICApOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb25IYW5kbGVyPjtcbn1cblxuZXhwb3J0IHsgcmVnaXN0ZXJCYWNrZW5kIH0gZnJvbSAnLi9iYWNrZW5kLWltcGwuanMnO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vLyBUaGlzIGZpbGUgaXMgZ2VuZXJhdGVkIGJ5IC9qcy9zY3JpcHRzL3VwZGF0ZS12ZXJzaW9uLnRzXG4vLyBEbyBub3QgbW9kaWZ5IGZpbGUgY29udGVudCBtYW51YWxseS5cblxuZXhwb3J0IGNvbnN0IHZlcnNpb24gPSAnMS4yMy4wJztcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRW52IH0gZnJvbSAnLi9lbnYuanMnO1xuaW1wb3J0IHsgdmVyc2lvbiB9IGZyb20gJy4vdmVyc2lvbi5qcyc7XG5cbnR5cGUgTG9nTGV2ZWxUeXBlID0gRW52Wydsb2dMZXZlbCddO1xuXG5sZXQgbG9nTGV2ZWxWYWx1ZTogUmVxdWlyZWQ8TG9nTGV2ZWxUeXBlPiA9ICd3YXJuaW5nJztcblxuZXhwb3J0IGNvbnN0IGVudjogRW52ID0ge1xuICB3YXNtOiB7fSBhcyBFbnYuV2ViQXNzZW1ibHlGbGFncyxcbiAgd2ViZ2w6IHt9IGFzIEVudi5XZWJHTEZsYWdzLFxuICB3ZWJncHU6IHt9IGFzIEVudi5XZWJHcHVGbGFncyxcbiAgdmVyc2lvbnM6IHsgY29tbW9uOiB2ZXJzaW9uIH0sXG5cbiAgc2V0IGxvZ0xldmVsKHZhbHVlOiBMb2dMZXZlbFR5cGUpIHtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJyB8fCBbJ3ZlcmJvc2UnLCAnaW5mbycsICd3YXJuaW5nJywgJ2Vycm9yJywgJ2ZhdGFsJ10uaW5kZXhPZih2YWx1ZSkgPT09IC0xKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGxvZ2dpbmcgbGV2ZWw6ICR7dmFsdWV9YCk7XG4gICAgfVxuICAgIGxvZ0xldmVsVmFsdWUgPSB2YWx1ZTtcbiAgfSxcbiAgZ2V0IGxvZ0xldmVsKCk6IFJlcXVpcmVkPExvZ0xldmVsVHlwZT4ge1xuICAgIHJldHVybiBsb2dMZXZlbFZhbHVlO1xuICB9LFxufTtcblxuLy8gc2V0IHByb3BlcnR5ICdsb2dMZXZlbCcgc28gdGhhdCB0aGV5IGNhbiBiZSBjb3JyZWN0bHkgdHJhbnNmZXJyZWQgdG8gd29ya2VyIGJ5IGBwb3N0TWVzc2FnZSgpYC5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShlbnYsICdsb2dMZXZlbCcsIHsgZW51bWVyYWJsZTogdHJ1ZSB9KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgZW52IGFzIGVudkltcGwgfSBmcm9tICcuL2Vudi1pbXBsLmpzJztcbmltcG9ydCB7IFRyeUdldEdsb2JhbFR5cGUgfSBmcm9tICcuL3R5cGUtaGVscGVyLmpzJztcblxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIEVudiB7XG4gIGV4cG9ydCB0eXBlIFdhc21QYXRoUHJlZml4ID0gc3RyaW5nO1xuICBleHBvcnQgaW50ZXJmYWNlIFdhc21GaWxlUGF0aHMge1xuICAgIC8qKlxuICAgICAqIFNwZWNpZnkgdGhlIG92ZXJyaWRlIHBhdGggZm9yIHRoZSBtYWluIC53YXNtIGZpbGUuXG4gICAgICpcbiAgICAgKiBUaGlzIHBhdGggc2hvdWxkIGJlIGFuIGFic29sdXRlIHBhdGguXG4gICAgICpcbiAgICAgKiBJZiBub3QgbW9kaWZpZWQsIHRoZSBmaWxlbmFtZSBvZiB0aGUgLndhc20gZmlsZSBpczpcbiAgICAgKiAtIGBvcnQtd2FzbS1zaW1kLXRocmVhZGVkLndhc21gIGZvciBkZWZhdWx0IGJ1aWxkXG4gICAgICogLSBgb3J0LXdhc20tc2ltZC10aHJlYWRlZC5qc2VwLndhc21gIGZvciBKU0VQIGJ1aWxkICh3aXRoIFdlYkdQVSBhbmQgV2ViTk4pXG4gICAgICovXG4gICAgd2FzbT86IFVSTCB8IHN0cmluZztcbiAgICAvKipcbiAgICAgKiBTcGVjaWZ5IHRoZSBvdmVycmlkZSBwYXRoIGZvciB0aGUgbWFpbiAubWpzIGZpbGUuXG4gICAgICpcbiAgICAgKiBUaGlzIHBhdGggc2hvdWxkIGJlIGFuIGFic29sdXRlIHBhdGguXG4gICAgICpcbiAgICAgKiBJZiBub3QgbW9kaWZpZWQsIHRoZSBmaWxlbmFtZSBvZiB0aGUgLm1qcyBmaWxlIGlzOlxuICAgICAqIC0gYG9ydC13YXNtLXNpbWQtdGhyZWFkZWQubWpzYCBmb3IgZGVmYXVsdCBidWlsZFxuICAgICAqIC0gYG9ydC13YXNtLXNpbWQtdGhyZWFkZWQuanNlcC5tanNgIGZvciBKU0VQIGJ1aWxkICh3aXRoIFdlYkdQVSBhbmQgV2ViTk4pXG4gICAgICovXG4gICAgbWpzPzogVVJMIHwgc3RyaW5nO1xuICB9XG4gIGV4cG9ydCB0eXBlIFdhc21QcmVmaXhPckZpbGVQYXRocyA9IFdhc21QYXRoUHJlZml4IHwgV2FzbUZpbGVQYXRocztcbiAgZXhwb3J0IGludGVyZmFjZSBXZWJBc3NlbWJseUZsYWdzIHtcbiAgICAvKipcbiAgICAgKiBzZXQgb3IgZ2V0IG51bWJlciBvZiB0aHJlYWQocykuIElmIG9taXR0ZWQgb3Igc2V0IHRvIDAsIG51bWJlciBvZiB0aHJlYWQocykgd2lsbCBiZSBkZXRlcm1pbmVkIGJ5IHN5c3RlbS4gSWYgc2V0XG4gICAgICogdG8gMSwgbm8gd29ya2VyIHRocmVhZCB3aWxsIGJlIHNwYXduZWQuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgd2hlbiBXZWJBc3NlbWJseSBtdWx0aXRocmVhZCBmZWF0dXJlIGlzIGF2YWlsYWJsZSBpbiBjdXJyZW50IGNvbnRleHQuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdFZhbHVlIGAwYFxuICAgICAqL1xuICAgIG51bVRocmVhZHM/OiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBzZXQgYSB2YWx1ZSBpbmRpY2F0aW5nIHdoZXRoZXIgdG8gZW5hYmxlIFNJTUQuXG4gICAgICpcbiAgICAgKiBPTk5YIFJ1bnRpbWUgd2lsbCBwZXJmb3JtIGZlYXR1cmUgZGV0ZWN0aW9uIGJhc2VkIG9uIHRoZSB2YWx1ZSBvZiB0aGlzIHByb3BlcnR5LiBTcGVjaWZpY2FsbHksIHdoZW4gdGhlIHZhbHVlIGlzXG4gICAgICogc2V0IHRvOlxuICAgICAqIC0gYHVuZGVmaW5lZGAsIGB0cnVlYCBvciBgXCJmaXhlZFwiYDogd2lsbCBjaGVjayBhdmFpbGFiaWxpdHkgb2YgRml4ZWQtd2lkdGggU0lNRC5cbiAgICAgKiAtIGBcInJlbGF4ZWRcImA6IHdpbGwgY2hlY2sgYXZhaWxhYmlsaXR5IG9mIFJlbGF4ZWQgU0lNRC5cbiAgICAgKiAtIGBmYWxzZWA6IHdpbGwgbm90IHBlcmZvcm0gU0lNRCBmZWF0dXJlIGNoZWNraW5nLlxuICAgICAqXG4gICAgICogU2V0dGluZyB0aGlzIHByb3BlcnR5IGRvZXMgbm90IG1ha2UgT05OWCBSdW50aW1lIHRvIHN3aXRjaCB0byB0aGUgY29ycmVzcG9uZGluZyBydW50aW1lIGF1dG9tYXRpY2FsbHkuIFVzZXIgbmVlZFxuICAgICAqIHRvIHNldCBgd2FzbVBhdGhzYCBvciBgd2FzbUJpbmFyeWAgcHJvcGVydHkgdG8gbG9hZCB0aGUgY29ycmVzcG9uZGluZyBydW50aW1lLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IHdoZW4gV2ViQXNzZW1ibHkgU0lNRCBmZWF0dXJlIGlzIGF2YWlsYWJsZSBpbiBjdXJyZW50IGNvbnRleHQuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdFZhbHVlIGB0cnVlYFxuICAgICAqL1xuICAgIHNpbWQ/OiBib29sZWFuIHwgJ2ZpeGVkJyB8ICdyZWxheGVkJztcblxuICAgIC8qKlxuICAgICAqIHNldCBvciBnZXQgYSBib29sZWFuIHZhbHVlIGluZGljYXRpbmcgd2hldGhlciB0byBlbmFibGUgdHJhY2UuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdFZhbHVlIGBmYWxzZWBcbiAgICAgKlxuICAgICAqIEBkZXByZWNhdGVkIFVzZSBgZW52LnRyYWNlYCBpbnN0ZWFkLiBJZiBgZW52LnRyYWNlYCBpcyBzZXQsIHRoaXMgcHJvcGVydHkgd2lsbCBiZSBpZ25vcmVkLlxuICAgICAqL1xuICAgIHRyYWNlPzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFNldCBvciBnZXQgYSBudW1iZXIgc3BlY2lmeWluZyB0aGUgdGltZW91dCBmb3IgaW5pdGlhbGl6YXRpb24gb2YgV2ViQXNzZW1ibHkgYmFja2VuZCwgaW4gbWlsbGlzZWNvbmRzLiBBIHplcm9cbiAgICAgKiB2YWx1ZSBpbmRpY2F0ZXMgbm8gdGltZW91dCBpcyBzZXQuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdFZhbHVlIGAwYFxuICAgICAqL1xuICAgIGluaXRUaW1lb3V0PzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogU2V0IGEgY3VzdG9tIFVSTCBwcmVmaXggdG8gdGhlIC53YXNtLy5tanMgZmlsZXMsIG9yIGFuIG9iamVjdCBvZiBvdmVycmlkZXMgZm9yIGJvdGggLndhc20vLm1qcyBmaWxlLiBUaGUgb3ZlcnJpZGVcbiAgICAgKiBwYXRoIHNob3VsZCBiZSBhbiBhYnNvbHV0ZSBwYXRoLlxuICAgICAqL1xuICAgIHdhc21QYXRocz86IFdhc21QcmVmaXhPckZpbGVQYXRocztcblxuICAgIC8qKlxuICAgICAqIFNldCBhIGN1c3RvbSBidWZmZXIgd2hpY2ggY29udGFpbnMgdGhlIFdlYkFzc2VtYmx5IGJpbmFyeS4gSWYgdGhpcyBwcm9wZXJ0eSBpcyBzZXQsIHRoZSBgd2FzbVBhdGhzYCBwcm9wZXJ0eSB3aWxsXG4gICAgICogYmUgaWdub3JlZC5cbiAgICAgKi9cbiAgICB3YXNtQmluYXJ5PzogQXJyYXlCdWZmZXJMaWtlIHwgVWludDhBcnJheTtcblxuICAgIC8qKlxuICAgICAqIFNldCBvciBnZXQgYSBib29sZWFuIHZhbHVlIGluZGljYXRpbmcgd2hldGhlciB0byBwcm94eSB0aGUgZXhlY3V0aW9uIG9mIG1haW4gdGhyZWFkIHRvIGEgd29ya2VyIHRocmVhZC5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0VmFsdWUgYGZhbHNlYFxuICAgICAqL1xuICAgIHByb3h5PzogYm9vbGVhbjtcbiAgfVxuXG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViR0xGbGFncyB7XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgV2ViR0wgQ29udGV4dCBJRCAod2ViZ2wgb3Igd2ViZ2wyKS5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0VmFsdWUgYCd3ZWJnbDInYFxuICAgICAqL1xuICAgIGNvbnRleHRJZD86ICd3ZWJnbCcgfCAnd2ViZ2wyJztcbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIFdlYkdMIHJlbmRlcmluZyBjb250ZXh0LlxuICAgICAqL1xuICAgIHJlYWRvbmx5IGNvbnRleHQ6IFdlYkdMUmVuZGVyaW5nQ29udGV4dDtcbiAgICAvKipcbiAgICAgKiBTZXQgb3IgZ2V0IHRoZSBtYXhpbXVtIGJhdGNoIHNpemUgZm9yIG1hdG11bC4gMCBtZWFucyB0byBkaXNhYmxlIGJhdGNoaW5nLlxuICAgICAqXG4gICAgICogQGRlcHJlY2F0ZWRcbiAgICAgKi9cbiAgICBtYXRtdWxNYXhCYXRjaFNpemU/OiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgdGV4dHVyZSBjYWNoZSBtb2RlLlxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgJ2Z1bGwnYFxuICAgICAqL1xuICAgIHRleHR1cmVDYWNoZU1vZGU/OiAnaW5pdGlhbGl6ZXJPbmx5JyB8ICdmdWxsJztcbiAgICAvKipcbiAgICAgKiBTZXQgb3IgZ2V0IHRoZSBwYWNrZWQgdGV4dHVyZSBtb2RlXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdFZhbHVlIGBmYWxzZWBcbiAgICAgKi9cbiAgICBwYWNrPzogYm9vbGVhbjtcbiAgICAvKipcbiAgICAgKiBTZXQgb3IgZ2V0IHdoZXRoZXIgZW5hYmxlIGFzeW5jIGRvd25sb2FkLlxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgZmFsc2VgXG4gICAgICovXG4gICAgYXN5bmM/OiBib29sZWFuO1xuICB9XG5cbiAgZXhwb3J0IGludGVyZmFjZSBXZWJHcHVQcm9maWxpbmdEYXRhVjFUZW5zb3JNZXRhZGF0YSB7XG4gICAgZGltczogcmVhZG9ubHkgbnVtYmVyW107XG4gICAgZGF0YVR5cGU6IHN0cmluZztcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIFdlYkdwdVByb2ZpbGluZ0RhdGFWMSB7XG4gICAgdmVyc2lvbjogMTtcbiAgICBpbnB1dHNNZXRhZGF0YTogcmVhZG9ubHkgV2ViR3B1UHJvZmlsaW5nRGF0YVYxVGVuc29yTWV0YWRhdGFbXTtcbiAgICBvdXRwdXRzTWV0YWRhdGE6IHJlYWRvbmx5IFdlYkdwdVByb2ZpbGluZ0RhdGFWMVRlbnNvck1ldGFkYXRhW107XG4gICAga2VybmVsSWQ6IG51bWJlcjtcbiAgICBrZXJuZWxUeXBlOiBzdHJpbmc7XG4gICAga2VybmVsTmFtZTogc3RyaW5nO1xuICAgIHByb2dyYW1OYW1lOiBzdHJpbmc7XG4gICAgc3RhcnRUaW1lOiBudW1iZXI7XG4gICAgZW5kVGltZTogbnVtYmVyO1xuICB9XG5cbiAgZXhwb3J0IHR5cGUgV2ViR3B1UHJvZmlsaW5nRGF0YSA9IFdlYkdwdVByb2ZpbGluZ0RhdGFWMTtcblxuICBleHBvcnQgaW50ZXJmYWNlIFdlYkdwdUZsYWdzIHtcbiAgICAvKipcbiAgICAgKiBTZXQgb3IgZ2V0IHRoZSBwcm9maWxpbmcgbW9kZS5cbiAgICAgKlxuICAgICAqIEBkZXByZWNhdGVkIFVzZSBgZW52LndlYmdwdS5wcm9maWxpbmcubW9kZWAgaW5zdGVhZC4gSWYgYGVudi53ZWJncHUucHJvZmlsaW5nLm1vZGVgIGlzIHNldCwgdGhpcyBwcm9wZXJ0eSB3aWxsIGJlXG4gICAgICogaWdub3JlZC5cbiAgICAgKi9cbiAgICBwcm9maWxpbmdNb2RlPzogJ29mZicgfCAnZGVmYXVsdCc7XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgcHJvZmlsaW5nIGNvbmZpZ3VyYXRpb24uXG4gICAgICovXG4gICAgcHJvZmlsaW5nOiB7XG4gICAgICAvKipcbiAgICAgICAqIFNldCBvciBnZXQgdGhlIHByb2ZpbGluZyBtb2RlLlxuICAgICAgICpcbiAgICAgICAqIEBkZWZhdWx0VmFsdWUgYCdvZmYnYFxuICAgICAgICovXG4gICAgICBtb2RlPzogJ29mZicgfCAnZGVmYXVsdCc7XG5cbiAgICAgIC8qKlxuICAgICAgICogU2V0IG9yIGdldCBhIGNhbGxiYWNrIGZ1bmN0aW9uIHdoZW4gYSBwcm9maWxpbmcgZGF0YSBpcyByZWNlaXZlZC4gSWYgbm90IHNldCwgdGhlIHByb2ZpbGluZyBkYXRhIHdpbGwgYmVcbiAgICAgICAqIHByaW50ZWQgdG8gY29uc29sZS5cbiAgICAgICAqL1xuICAgICAgb25kYXRhPzogKGRhdGE6IFdlYkdwdVByb2ZpbGluZ0RhdGEpID0+IHZvaWQ7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBTZXQgb3IgZ2V0IHRoZSBwb3dlciBwcmVmZXJlbmNlLlxuICAgICAqXG4gICAgICogU2V0dGluZyB0aGlzIHByb3BlcnR5IG9ubHkgaGFzIGVmZmVjdCBiZWZvcmUgdGhlIGZpcnN0IFdlYkdQVSBpbmZlcmVuY2Ugc2Vzc2lvbiBpcyBjcmVhdGVkLiBUaGUgdmFsdWUgd2lsbCBiZVxuICAgICAqIHVzZWQgYXMgb3B0aW9ucyBmb3IgYG5hdmlnYXRvci5ncHUucmVxdWVzdEFkYXB0ZXIoKWAuXG4gICAgICpcbiAgICAgKiBTZWUge0BsaW5rIGh0dHBzOi8vZ3B1d2ViLmdpdGh1Yi5pby9ncHV3ZWIvI2RpY3RkZWYtZ3B1cmVxdWVzdGFkYXB0ZXJvcHRpb25zfSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgdW5kZWZpbmVkYFxuICAgICAqXG4gICAgICogQGRlcHJlY2F0ZWQgQ3JlYXRlIHlvdXIgb3duIEdQVUFkYXB0ZXIsIHVzZSBpdCB0byBjcmVhdGUgYSBHUFVEZXZpY2UgaW5zdGFuY2UgYW5kIHNldCB7QGxpbmsgZGV2aWNlfSBwcm9wZXJ0eSBpZlxuICAgICAqIHlvdSB3YW50IHRvIHVzZSBhIHNwZWNpZmljIHBvd2VyIHByZWZlcmVuY2UuXG4gICAgICovXG4gICAgcG93ZXJQcmVmZXJlbmNlPzogJ2xvdy1wb3dlcicgfCAnaGlnaC1wZXJmb3JtYW5jZSc7XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgZm9yY2UgZmFsbGJhY2sgYWRhcHRlciBmbGFnLlxuICAgICAqXG4gICAgICogU2V0dGluZyB0aGlzIHByb3BlcnR5IG9ubHkgaGFzIGVmZmVjdCBiZWZvcmUgdGhlIGZpcnN0IFdlYkdQVSBpbmZlcmVuY2Ugc2Vzc2lvbiBpcyBjcmVhdGVkLiBUaGUgdmFsdWUgd2lsbCBiZVxuICAgICAqIHVzZWQgYXMgb3B0aW9ucyBmb3IgYG5hdmlnYXRvci5ncHUucmVxdWVzdEFkYXB0ZXIoKWAuXG4gICAgICpcbiAgICAgKiBTZWUge0BsaW5rIGh0dHBzOi8vZ3B1d2ViLmdpdGh1Yi5pby9ncHV3ZWIvI2RpY3RkZWYtZ3B1cmVxdWVzdGFkYXB0ZXJvcHRpb25zfSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgdW5kZWZpbmVkYFxuICAgICAqXG4gICAgICogQGRlcHJlY2F0ZWQgQ3JlYXRlIHlvdXIgb3duIEdQVUFkYXB0ZXIsIHVzZSBpdCB0byBjcmVhdGUgYSBHUFVEZXZpY2UgaW5zdGFuY2UgYW5kIHNldCB7QGxpbmsgZGV2aWNlfSBwcm9wZXJ0eSBpZlxuICAgICAqIHlvdSB3YW50IHRvIHVzZSBhIHNwZWNpZmljIGZhbGxiYWNrIG9wdGlvbi5cbiAgICAgKi9cbiAgICBmb3JjZUZhbGxiYWNrQWRhcHRlcj86IGJvb2xlYW47XG4gICAgLyoqXG4gICAgICogU2V0IG9yIGdldCB0aGUgYWRhcHRlciBmb3IgV2ViR1BVLlxuICAgICAqXG4gICAgICogU2V0dGluZyB0aGlzIHByb3BlcnR5IG9ubHkgaGFzIGVmZmVjdCBiZWZvcmUgdGhlIGZpcnN0IFdlYkdQVSBpbmZlcmVuY2Ugc2Vzc2lvbiBpcyBjcmVhdGVkLiBUaGUgdmFsdWUgd2lsbCBiZVxuICAgICAqIHVzZWQgYXMgdGhlIEdQVSBhZGFwdGVyIGZvciB0aGUgdW5kZXJseWluZyBXZWJHUFUgYmFja2VuZCB0byBjcmVhdGUgR1BVIGRldmljZS5cbiAgICAgKlxuICAgICAqIElmIHRoaXMgcHJvcGVydHkgaXMgbm90IHNldCwgaXQgd2lsbCBiZSBhdmFpbGFibGUgdG8gZ2V0IGFmdGVyIHRoZSBmaXJzdCBXZWJHUFUgaW5mZXJlbmNlIHNlc3Npb24gaXMgY3JlYXRlZC4gVGhlXG4gICAgICogdmFsdWUgd2lsbCBiZSB0aGUgR1BVIGFkYXB0ZXIgdGhhdCBjcmVhdGVkIGJ5IHRoZSB1bmRlcmx5aW5nIFdlYkdQVSBiYWNrZW5kLlxuICAgICAqXG4gICAgICogV2hlbiB1c2Ugd2l0aCBUeXBlU2NyaXB0LCB0aGUgdHlwZSBvZiB0aGlzIHByb3BlcnR5IGlzIGBHUFVBZGFwdGVyYCBkZWZpbmVkIGluIFwiQHdlYmdwdS90eXBlc1wiLlxuICAgICAqXG4gICAgICogQGRlcHJlY2F0ZWQgSXQgaXMgbm8gbG9uZ2VyIHJlY29tbWVuZGVkIHRvIHVzZSB0aGlzIHByb3BlcnR5LiBUaGUgbGF0ZXN0IFdlYkdQVSBzcGVjIGFkZHMgYEdQVURldmljZS5hZGFwdGVySW5mb2BcbiAgICAgKiAoaHR0cHM6Ly93d3cudzMub3JnL1RSL3dlYmdwdS8jZG9tLWdwdWRldmljZS1hZGFwdGVyaW5mbyksIHdoaWNoIGFsbG93cyB0byBnZXQgdGhlIGFkYXB0ZXIgaW5mb3JtYXRpb24gZnJvbSB0aGVcbiAgICAgKiBkZXZpY2UuIFdoZW4gaXQncyBhdmFpbGFibGUsIHRoZXJlIGlzIG5vIG5lZWQgdG8gc2V0L2dldCB0aGUge0BsaW5rIGFkYXB0ZXJ9IHByb3BlcnR5LlxuICAgICAqL1xuICAgIGFkYXB0ZXI6IFRyeUdldEdsb2JhbFR5cGU8J0dQVUFkYXB0ZXInPjtcbiAgICAvKipcbiAgICAgKiBTZXQgb3IgZ2V0IHRoZSBHUFUgZGV2aWNlIGZvciBXZWJHUFUuXG4gICAgICpcbiAgICAgKiBUaGVyZSBhcmUgMyB2YWxpZCBzY2VuYXJpb3Mgb2YgYWNjZXNzaW5nIHRoaXMgcHJvcGVydHk6XG4gICAgICogLSBTZXQgYSB2YWx1ZSBiZWZvcmUgdGhlIGZpcnN0IFdlYkdQVSBpbmZlcmVuY2Ugc2Vzc2lvbiBpcyBjcmVhdGVkLiBUaGUgdmFsdWUgd2lsbCBiZSB1c2VkIGJ5IHRoZSBXZWJHUFUgYmFja2VuZFxuICAgICAqIHRvIHBlcmZvcm0gY2FsY3VsYXRpb25zLiBJZiB0aGUgdmFsdWUgaXMgbm90IGEgYEdQVURldmljZWAgb2JqZWN0LCBhbiBlcnJvciB3aWxsIGJlIHRocm93bi5cbiAgICAgKiAtIEdldCB0aGUgdmFsdWUgYmVmb3JlIHRoZSBmaXJzdCBXZWJHUFUgaW5mZXJlbmNlIHNlc3Npb24gaXMgY3JlYXRlZC4gVGhpcyB3aWxsIHRyeSB0byBjcmVhdGUgYSBuZXcgR1BVRGV2aWNlXG4gICAgICogaW5zdGFuY2UuIFJldHVybnMgYSBgUHJvbWlzZWAgdGhhdCByZXNvbHZlcyB0byBhIGBHUFVEZXZpY2VgIG9iamVjdC5cbiAgICAgKiAtIEdldCB0aGUgdmFsdWUgYWZ0ZXIgdGhlIGZpcnN0IFdlYkdQVSBpbmZlcmVuY2Ugc2Vzc2lvbiBpcyBjcmVhdGVkLiBSZXR1cm5zIGEgcmVzb2x2ZWQgYFByb21pc2VgIHRvIHRoZVxuICAgICAqIGBHUFVEZXZpY2VgIG9iamVjdCB1c2VkIGJ5IHRoZSBXZWJHUFUgYmFja2VuZC5cbiAgICAgKi9cbiAgICBnZXQgZGV2aWNlKCk6IFByb21pc2U8VHJ5R2V0R2xvYmFsVHlwZTwnR1BVRGV2aWNlJz4+O1xuICAgIHNldCBkZXZpY2UodmFsdWU6IFRyeUdldEdsb2JhbFR5cGU8J0dQVURldmljZSc+KTtcbiAgICAvKipcbiAgICAgKiBTZXQgb3IgZ2V0IHdoZXRoZXIgdmFsaWRhdGUgaW5wdXQgY29udGVudC5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0VmFsdWUgYGZhbHNlYFxuICAgICAqL1xuICAgIHZhbGlkYXRlSW5wdXRDb250ZW50PzogYm9vbGVhbjtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVudiB7XG4gIC8qKlxuICAgKiBzZXQgdGhlIHNldmVyaXR5IGxldmVsIGZvciBsb2dnaW5nLlxuICAgKlxuICAgKiBAZGVmYXVsdFZhbHVlIGAnd2FybmluZydgXG4gICAqL1xuICBsb2dMZXZlbD86ICd2ZXJib3NlJyB8ICdpbmZvJyB8ICd3YXJuaW5nJyB8ICdlcnJvcicgfCAnZmF0YWwnO1xuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZSB3aGV0aGVyIHJ1biBpbiBkZWJ1ZyBtb2RlLlxuICAgKlxuICAgKiBAZGVmYXVsdFZhbHVlIGBmYWxzZWBcbiAgICovXG4gIGRlYnVnPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogc2V0IG9yIGdldCBhIGJvb2xlYW4gdmFsdWUgaW5kaWNhdGluZyB3aGV0aGVyIHRvIGVuYWJsZSB0cmFjZS5cbiAgICpcbiAgICogQGRlZmF1bHRWYWx1ZSBgZmFsc2VgXG4gICAqL1xuICB0cmFjZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEdldCB2ZXJzaW9uIG9mIHRoZSBjdXJyZW50IHBhY2thZ2UuXG4gICAqL1xuICByZWFkb25seSB2ZXJzaW9uczoge1xuICAgIHJlYWRvbmx5IGNvbW1vbjogc3RyaW5nO1xuICAgIHJlYWRvbmx5IHdlYj86IHN0cmluZztcbiAgICByZWFkb25seSBub2RlPzogc3RyaW5nO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cbiAgICByZWFkb25seSAncmVhY3QtbmF0aXZlJz86IHN0cmluZztcbiAgfTtcblxuICAvKipcbiAgICogUmVwcmVzZW50IGEgc2V0IG9mIGZsYWdzIGZvciBXZWJBc3NlbWJseVxuICAgKi9cbiAgcmVhZG9ubHkgd2FzbTogRW52LldlYkFzc2VtYmx5RmxhZ3M7XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudCBhIHNldCBvZiBmbGFncyBmb3IgV2ViR0xcbiAgICovXG4gIHJlYWRvbmx5IHdlYmdsOiBFbnYuV2ViR0xGbGFncztcblxuICAvKipcbiAgICogUmVwcmVzZW50IGEgc2V0IG9mIGZsYWdzIGZvciBXZWJHUFVcbiAgICovXG4gIHJlYWRvbmx5IHdlYmdwdTogRW52LldlYkdwdUZsYWdzO1xuXG4gIFtuYW1lOiBzdHJpbmddOiB1bmtub3duO1xufVxuXG4vKipcbiAqIFJlcHJlc2VudCBhIHNldCBvZiBmbGFncyBhcyBhIGdsb2JhbCBzaW5nbGV0b24uXG4gKi9cbmV4cG9ydCBjb25zdCBlbnY6IEVudiA9IGVudkltcGw7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvclRvRGF0YVVybE9wdGlvbnMsIFRlbnNvclRvSW1hZ2VEYXRhT3B0aW9ucyB9IGZyb20gJy4vdGVuc29yLWNvbnZlcnNpb24uanMnO1xuaW1wb3J0IHsgVGVuc29yIH0gZnJvbSAnLi90ZW5zb3IuanMnO1xuXG4vKipcbiAqIGltcGxlbWVudGF0aW9uIG9mIFRlbnNvci50b0RhdGFVUkwoKVxuICovXG5leHBvcnQgY29uc3QgdGVuc29yVG9EYXRhVVJMID0gKHRlbnNvcjogVGVuc29yLCBvcHRpb25zPzogVGVuc29yVG9EYXRhVXJsT3B0aW9ucyk6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGNhbnZhcyA9IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgPyBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKSA6IG5ldyBPZmZzY3JlZW5DYW52YXMoMSwgMSk7XG4gIGNhbnZhcy53aWR0aCA9IHRlbnNvci5kaW1zWzNdO1xuICBjYW52YXMuaGVpZ2h0ID0gdGVuc29yLmRpbXNbMl07XG4gIGNvbnN0IHBpeGVsczJEQ29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpIGFzXG4gICAgfCBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkRcbiAgICB8IE9mZnNjcmVlbkNhbnZhc1JlbmRlcmluZ0NvbnRleHQyRFxuICAgIHwgbnVsbDtcblxuICBpZiAocGl4ZWxzMkRDb250ZXh0ICE9IG51bGwpIHtcbiAgICAvLyBEZWZhdWx0IHZhbHVlcyBmb3IgaGVpZ2h0IGFuZCB3aWR0aCAmIGZvcm1hdFxuICAgIGxldCB3aWR0aDogbnVtYmVyO1xuICAgIGxldCBoZWlnaHQ6IG51bWJlcjtcbiAgICBpZiAob3B0aW9ucz8udGVuc29yTGF5b3V0ICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy50ZW5zb3JMYXlvdXQgPT09ICdOSFdDJykge1xuICAgICAgd2lkdGggPSB0ZW5zb3IuZGltc1syXTtcbiAgICAgIGhlaWdodCA9IHRlbnNvci5kaW1zWzNdO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBEZWZhdWx0IGxheW91dCBpcyBOQ1dIXG4gICAgICB3aWR0aCA9IHRlbnNvci5kaW1zWzNdO1xuICAgICAgaGVpZ2h0ID0gdGVuc29yLmRpbXNbMl07XG4gICAgfVxuXG4gICAgY29uc3QgaW5wdXRmb3JtYXQgPSBvcHRpb25zPy5mb3JtYXQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZm9ybWF0IDogJ1JHQic7XG5cbiAgICBjb25zdCBub3JtID0gb3B0aW9ucz8ubm9ybTtcbiAgICBsZXQgbm9ybU1lYW46IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICAgIGxldCBub3JtQmlhczogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gICAgaWYgKG5vcm0gPT09IHVuZGVmaW5lZCB8fCBub3JtLm1lYW4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgbm9ybU1lYW4gPSBbMjU1LCAyNTUsIDI1NSwgMjU1XTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHR5cGVvZiBub3JtLm1lYW4gPT09ICdudW1iZXInKSB7XG4gICAgICAgIG5vcm1NZWFuID0gW25vcm0ubWVhbiwgbm9ybS5tZWFuLCBub3JtLm1lYW4sIG5vcm0ubWVhbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBub3JtTWVhbiA9IFtub3JtLm1lYW5bMF0sIG5vcm0ubWVhblsxXSwgbm9ybS5tZWFuWzJdLCAwXTtcbiAgICAgICAgaWYgKG5vcm0ubWVhblszXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbm9ybU1lYW5bM10gPSBub3JtLm1lYW5bM107XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG5vcm0gPT09IHVuZGVmaW5lZCB8fCBub3JtLmJpYXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgbm9ybUJpYXMgPSBbMCwgMCwgMCwgMF07XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0eXBlb2Ygbm9ybS5iaWFzID09PSAnbnVtYmVyJykge1xuICAgICAgICBub3JtQmlhcyA9IFtub3JtLmJpYXMsIG5vcm0uYmlhcywgbm9ybS5iaWFzLCBub3JtLmJpYXNdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9ybUJpYXMgPSBbbm9ybS5iaWFzWzBdLCBub3JtLmJpYXNbMV0sIG5vcm0uYmlhc1syXSwgMF07XG4gICAgICAgIGlmIChub3JtLmJpYXNbM10gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG5vcm1CaWFzWzNdID0gbm9ybS5iaWFzWzNdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgc3RyaWRlID0gaGVpZ2h0ICogd2lkdGg7XG4gICAgLy8gRGVmYXVsdCBwb2ludGVyIGFzc2lnbm1lbnRzXG4gICAgbGV0IHJUZW5zb3JQb2ludGVyID0gMCxcbiAgICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlLFxuICAgICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyLFxuICAgICAgYVRlbnNvclBvaW50ZXIgPSAtMTtcblxuICAgIC8vIFVwZGF0aW5nIHRoZSBwb2ludGVyIGFzc2lnbm1lbnRzIGJhc2VkIG9uIHRoZSBpbnB1dCBpbWFnZSBmb3JtYXRcbiAgICBpZiAoaW5wdXRmb3JtYXQgPT09ICdSR0JBJykge1xuICAgICAgclRlbnNvclBvaW50ZXIgPSAwO1xuICAgICAgZ1RlbnNvclBvaW50ZXIgPSBzdHJpZGU7XG4gICAgICBiVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDI7XG4gICAgICBhVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDM7XG4gICAgfSBlbHNlIGlmIChpbnB1dGZvcm1hdCA9PT0gJ1JHQicpIHtcbiAgICAgIHJUZW5zb3JQb2ludGVyID0gMDtcbiAgICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlO1xuICAgICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyO1xuICAgIH0gZWxzZSBpZiAoaW5wdXRmb3JtYXQgPT09ICdSQkcnKSB7XG4gICAgICByVGVuc29yUG9pbnRlciA9IDA7XG4gICAgICBiVGVuc29yUG9pbnRlciA9IHN0cmlkZTtcbiAgICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMjtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGhlaWdodDsgaSsrKSB7XG4gICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHdpZHRoOyBqKyspIHtcbiAgICAgICAgY29uc3QgUiA9ICgodGVuc29yLmRhdGFbclRlbnNvclBvaW50ZXIrK10gYXMgbnVtYmVyKSAtIG5vcm1CaWFzWzBdKSAqIG5vcm1NZWFuWzBdOyAvLyBSIHZhbHVlXG4gICAgICAgIGNvbnN0IEcgPSAoKHRlbnNvci5kYXRhW2dUZW5zb3JQb2ludGVyKytdIGFzIG51bWJlcikgLSBub3JtQmlhc1sxXSkgKiBub3JtTWVhblsxXTsgLy8gRyB2YWx1ZVxuICAgICAgICBjb25zdCBCID0gKCh0ZW5zb3IuZGF0YVtiVGVuc29yUG9pbnRlcisrXSBhcyBudW1iZXIpIC0gbm9ybUJpYXNbMl0pICogbm9ybU1lYW5bMl07IC8vIEIgdmFsdWVcbiAgICAgICAgY29uc3QgQSA9IGFUZW5zb3JQb2ludGVyID09PSAtMSA/IDI1NSA6ICgodGVuc29yLmRhdGFbYVRlbnNvclBvaW50ZXIrK10gYXMgbnVtYmVyKSAtIG5vcm1CaWFzWzNdKSAqIG5vcm1NZWFuWzNdOyAvLyBBIHZhbHVlXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvcmVzdHJpY3QtcGx1cy1vcGVyYW5kc1xuICAgICAgICBwaXhlbHMyRENvbnRleHQuZmlsbFN0eWxlID0gJ3JnYmEoJyArIFIgKyAnLCcgKyBHICsgJywnICsgQiArICcsJyArIEEgKyAnKSc7XG4gICAgICAgIHBpeGVsczJEQ29udGV4dC5maWxsUmVjdChqLCBpLCAxLCAxKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCd0b0RhdGFVUkwnIGluIGNhbnZhcykge1xuICAgICAgcmV0dXJuIGNhbnZhcy50b0RhdGFVUkwoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd0b0RhdGFVUkwgaXMgbm90IHN1cHBvcnRlZCcpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEnKTtcbiAgfVxufTtcblxuLyoqXG4gKiBpbXBsZW1lbnRhdGlvbiBvZiBUZW5zb3IudG9JbWFnZURhdGEoKVxuICovXG5leHBvcnQgY29uc3QgdGVuc29yVG9JbWFnZURhdGEgPSAodGVuc29yOiBUZW5zb3IsIG9wdGlvbnM/OiBUZW5zb3JUb0ltYWdlRGF0YU9wdGlvbnMpOiBJbWFnZURhdGEgPT4ge1xuICBjb25zdCBwaXhlbHMyRENvbnRleHQgPVxuICAgIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJykuZ2V0Q29udGV4dCgnMmQnKVxuICAgICAgOiAobmV3IE9mZnNjcmVlbkNhbnZhcygxLCAxKS5nZXRDb250ZXh0KCcyZCcpIGFzIE9mZnNjcmVlbkNhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCk7XG4gIGxldCBpbWFnZTogSW1hZ2VEYXRhO1xuICBpZiAocGl4ZWxzMkRDb250ZXh0ICE9IG51bGwpIHtcbiAgICAvLyBEZWZhdWx0IHZhbHVlcyBmb3IgaGVpZ2h0IGFuZCB3aWR0aCAmIGZvcm1hdFxuICAgIGxldCB3aWR0aDogbnVtYmVyO1xuICAgIGxldCBoZWlnaHQ6IG51bWJlcjtcbiAgICBsZXQgY2hhbm5lbHM6IG51bWJlcjtcbiAgICBpZiAob3B0aW9ucz8udGVuc29yTGF5b3V0ICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy50ZW5zb3JMYXlvdXQgPT09ICdOSFdDJykge1xuICAgICAgd2lkdGggPSB0ZW5zb3IuZGltc1syXTtcbiAgICAgIGhlaWdodCA9IHRlbnNvci5kaW1zWzFdO1xuICAgICAgY2hhbm5lbHMgPSB0ZW5zb3IuZGltc1szXTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRGVmYXVsdCBsYXlvdXQgaXMgTkNXSFxuICAgICAgd2lkdGggPSB0ZW5zb3IuZGltc1szXTtcbiAgICAgIGhlaWdodCA9IHRlbnNvci5kaW1zWzJdO1xuICAgICAgY2hhbm5lbHMgPSB0ZW5zb3IuZGltc1sxXTtcbiAgICB9XG4gICAgY29uc3QgaW5wdXRmb3JtYXQgPSBvcHRpb25zICE9PSB1bmRlZmluZWQgPyAob3B0aW9ucy5mb3JtYXQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZm9ybWF0IDogJ1JHQicpIDogJ1JHQic7XG5cbiAgICBjb25zdCBub3JtID0gb3B0aW9ucz8ubm9ybTtcbiAgICBsZXQgbm9ybU1lYW46IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICAgIGxldCBub3JtQmlhczogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gICAgaWYgKG5vcm0gPT09IHVuZGVmaW5lZCB8fCBub3JtLm1lYW4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgbm9ybU1lYW4gPSBbMjU1LCAyNTUsIDI1NSwgMjU1XTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHR5cGVvZiBub3JtLm1lYW4gPT09ICdudW1iZXInKSB7XG4gICAgICAgIG5vcm1NZWFuID0gW25vcm0ubWVhbiwgbm9ybS5tZWFuLCBub3JtLm1lYW4sIG5vcm0ubWVhbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBub3JtTWVhbiA9IFtub3JtLm1lYW5bMF0sIG5vcm0ubWVhblsxXSwgbm9ybS5tZWFuWzJdLCAyNTVdO1xuICAgICAgICBpZiAobm9ybS5tZWFuWzNdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBub3JtTWVhblszXSA9IG5vcm0ubWVhblszXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBpZiAobm9ybSA9PT0gdW5kZWZpbmVkIHx8IG5vcm0uYmlhcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBub3JtQmlhcyA9IFswLCAwLCAwLCAwXTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHR5cGVvZiBub3JtLmJpYXMgPT09ICdudW1iZXInKSB7XG4gICAgICAgIG5vcm1CaWFzID0gW25vcm0uYmlhcywgbm9ybS5iaWFzLCBub3JtLmJpYXMsIG5vcm0uYmlhc107XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBub3JtQmlhcyA9IFtub3JtLmJpYXNbMF0sIG5vcm0uYmlhc1sxXSwgbm9ybS5iaWFzWzJdLCAwXTtcbiAgICAgICAgaWYgKG5vcm0uYmlhc1szXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbm9ybUJpYXNbM10gPSBub3JtLmJpYXNbM107XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBzdHJpZGUgPSBoZWlnaHQgKiB3aWR0aDtcbiAgICBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoXG4gICAgICAgIChvcHRpb25zLmZvcm1hdCAhPT0gdW5kZWZpbmVkICYmIGNoYW5uZWxzID09PSA0ICYmIG9wdGlvbnMuZm9ybWF0ICE9PSAnUkdCQScpIHx8XG4gICAgICAgIChjaGFubmVscyA9PT0gMyAmJiBvcHRpb25zLmZvcm1hdCAhPT0gJ1JHQicgJiYgb3B0aW9ucy5mb3JtYXQgIT09ICdCR1InKVxuICAgICAgKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRlbnNvciBmb3JtYXQgZG9lc24ndCBtYXRjaCBpbnB1dCB0ZW5zb3IgZGltc1wiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEZWZhdWx0IHBvaW50ZXIgYXNzaWdubWVudHNcbiAgICBjb25zdCBzdGVwID0gNDtcbiAgICBsZXQgckltYWdlUG9pbnRlciA9IDAsXG4gICAgICBnSW1hZ2VQb2ludGVyID0gMSxcbiAgICAgIGJJbWFnZVBvaW50ZXIgPSAyLFxuICAgICAgYUltYWdlUG9pbnRlciA9IDM7XG4gICAgbGV0IHJUZW5zb3JQb2ludGVyID0gMCxcbiAgICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlLFxuICAgICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyLFxuICAgICAgYVRlbnNvclBvaW50ZXIgPSAtMTtcblxuICAgIC8vIFVwZGF0aW5nIHRoZSBwb2ludGVyIGFzc2lnbm1lbnRzIGJhc2VkIG9uIHRoZSBpbnB1dCBpbWFnZSBmb3JtYXRcbiAgICBpZiAoaW5wdXRmb3JtYXQgPT09ICdSR0JBJykge1xuICAgICAgclRlbnNvclBvaW50ZXIgPSAwO1xuICAgICAgZ1RlbnNvclBvaW50ZXIgPSBzdHJpZGU7XG4gICAgICBiVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDI7XG4gICAgICBhVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDM7XG4gICAgfSBlbHNlIGlmIChpbnB1dGZvcm1hdCA9PT0gJ1JHQicpIHtcbiAgICAgIHJUZW5zb3JQb2ludGVyID0gMDtcbiAgICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlO1xuICAgICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyO1xuICAgIH0gZWxzZSBpZiAoaW5wdXRmb3JtYXQgPT09ICdSQkcnKSB7XG4gICAgICByVGVuc29yUG9pbnRlciA9IDA7XG4gICAgICBiVGVuc29yUG9pbnRlciA9IHN0cmlkZTtcbiAgICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMjtcbiAgICB9XG5cbiAgICBpbWFnZSA9IHBpeGVsczJEQ29udGV4dC5jcmVhdGVJbWFnZURhdGEod2lkdGgsIGhlaWdodCk7XG5cbiAgICBmb3IgKFxuICAgICAgbGV0IGkgPSAwO1xuICAgICAgaSA8IGhlaWdodCAqIHdpZHRoO1xuICAgICAgckltYWdlUG9pbnRlciArPSBzdGVwLCBnSW1hZ2VQb2ludGVyICs9IHN0ZXAsIGJJbWFnZVBvaW50ZXIgKz0gc3RlcCwgYUltYWdlUG9pbnRlciArPSBzdGVwLCBpKytcbiAgICApIHtcbiAgICAgIGltYWdlLmRhdGFbckltYWdlUG9pbnRlcl0gPSAoKHRlbnNvci5kYXRhW3JUZW5zb3JQb2ludGVyKytdIGFzIG51bWJlcikgLSBub3JtQmlhc1swXSkgKiBub3JtTWVhblswXTsgLy8gUiB2YWx1ZVxuICAgICAgaW1hZ2UuZGF0YVtnSW1hZ2VQb2ludGVyXSA9ICgodGVuc29yLmRhdGFbZ1RlbnNvclBvaW50ZXIrK10gYXMgbnVtYmVyKSAtIG5vcm1CaWFzWzFdKSAqIG5vcm1NZWFuWzFdOyAvLyBHIHZhbHVlXG4gICAgICBpbWFnZS5kYXRhW2JJbWFnZVBvaW50ZXJdID0gKCh0ZW5zb3IuZGF0YVtiVGVuc29yUG9pbnRlcisrXSBhcyBudW1iZXIpIC0gbm9ybUJpYXNbMl0pICogbm9ybU1lYW5bMl07IC8vIEIgdmFsdWVcbiAgICAgIGltYWdlLmRhdGFbYUltYWdlUG9pbnRlcl0gPVxuICAgICAgICBhVGVuc29yUG9pbnRlciA9PT0gLTEgPyAyNTUgOiAoKHRlbnNvci5kYXRhW2FUZW5zb3JQb2ludGVyKytdIGFzIG51bWJlcikgLSBub3JtQmlhc1szXSkgKiBub3JtTWVhblszXTsgLy8gQSB2YWx1ZVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEnKTtcbiAgfVxuICByZXR1cm4gaW1hZ2U7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1xuICBPcHRpb25zRGltZW5zaW9ucyxcbiAgT3B0aW9uc0Zvcm1hdCxcbiAgT3B0aW9uc05vcm1hbGl6YXRpb25QYXJhbWV0ZXJzLFxuICBPcHRpb25zVGVuc29yRm9ybWF0LFxuICBPcHRpb25zVGVuc29yTGF5b3V0LFxuICBUZW5zb3JGcm9tR3B1QnVmZmVyT3B0aW9ucyxcbiAgVGVuc29yRnJvbUltYWdlQml0bWFwT3B0aW9ucyxcbiAgVGVuc29yRnJvbUltYWdlRGF0YU9wdGlvbnMsXG4gIFRlbnNvckZyb21JbWFnZUVsZW1lbnRPcHRpb25zLFxuICBUZW5zb3JGcm9tTUxUZW5zb3JPcHRpb25zLFxuICBUZW5zb3JGcm9tVGV4dHVyZU9wdGlvbnMsXG4gIFRlbnNvckZyb21VcmxPcHRpb25zLFxufSBmcm9tICcuL3RlbnNvci1mYWN0b3J5LmpzJztcbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJy4vdGVuc29yLWltcGwuanMnO1xuaW1wb3J0IHsgVGVuc29yIGFzIFRlbnNvckludGVyZmFjZSB9IGZyb20gJy4vdGVuc29yLmpzJztcblxuaW50ZXJmYWNlIEJ1ZmZlclRvVGVuc29yT3B0aW9uc1xuICBleHRlbmRzIE9wdGlvbnNEaW1lbnNpb25zLFxuICAgIE9wdGlvbnNUZW5zb3JMYXlvdXQsXG4gICAgT3B0aW9uc05vcm1hbGl6YXRpb25QYXJhbWV0ZXJzLFxuICAgIE9wdGlvbnNGb3JtYXQsXG4gICAgT3B0aW9uc1RlbnNvckZvcm1hdCB7fVxuXG4vKipcbiAqIENyZWF0ZSBhIG5ldyB0ZW5zb3Igb2JqZWN0IGZyb20gaW1hZ2Ugb2JqZWN0XG4gKlxuICogQHBhcmFtIGJ1ZmZlciAtIEV4dHJhY3RlZCBpbWFnZSBidWZmZXIgZGF0YSAtIGFzc3VtaW5nIFJHQkEgZm9ybWF0XG4gKiBAcGFyYW0gaW1hZ2VGb3JtYXQgLSBpbnB1dCBpbWFnZSBjb25maWd1cmF0aW9uIC0gcmVxdWlyZWQgY29uZmlndXJhdGlvbnMgaGVpZ2h0LCB3aWR0aCwgZm9ybWF0XG4gKiBAcGFyYW0gdGVuc29yRm9ybWF0IC0gb3V0cHV0IHRlbnNvciBjb25maWd1cmF0aW9uIC0gRGVmYXVsdCBpcyBSR0IgZm9ybWF0XG4gKi9cbmV4cG9ydCBjb25zdCBidWZmZXJUb1RlbnNvciA9IChidWZmZXI6IFVpbnQ4Q2xhbXBlZEFycmF5IHwgdW5kZWZpbmVkLCBvcHRpb25zOiBCdWZmZXJUb1RlbnNvck9wdGlvbnMpOiBUZW5zb3IgPT4ge1xuICBpZiAoYnVmZmVyID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlIGJ1ZmZlciBtdXN0IGJlIGRlZmluZWQnKTtcbiAgfVxuICBpZiAob3B0aW9ucy5oZWlnaHQgPT09IHVuZGVmaW5lZCB8fCBvcHRpb25zLndpZHRoID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlIGhlaWdodCBhbmQgd2lkdGggbXVzdCBiZSBkZWZpbmVkJyk7XG4gIH1cbiAgaWYgKG9wdGlvbnMudGVuc29yTGF5b3V0ID09PSAnTkhXQycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05IV0MgVGVuc29yIGxheW91dCBpcyBub3Qgc3VwcG9ydGVkIHlldCcpO1xuICB9XG5cbiAgY29uc3QgeyBoZWlnaHQsIHdpZHRoIH0gPSBvcHRpb25zO1xuXG4gIGNvbnN0IG5vcm0gPSBvcHRpb25zLm5vcm0gPz8geyBtZWFuOiAyNTUsIGJpYXM6IDAgfTtcbiAgbGV0IG5vcm1NZWFuOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgbGV0IG5vcm1CaWFzOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcblxuICBpZiAodHlwZW9mIG5vcm0ubWVhbiA9PT0gJ251bWJlcicpIHtcbiAgICBub3JtTWVhbiA9IFtub3JtLm1lYW4sIG5vcm0ubWVhbiwgbm9ybS5tZWFuLCBub3JtLm1lYW5dO1xuICB9IGVsc2Uge1xuICAgIG5vcm1NZWFuID0gW25vcm0ubWVhbiFbMF0sIG5vcm0ubWVhbiFbMV0sIG5vcm0ubWVhbiFbMl0sIG5vcm0ubWVhbiFbM10gPz8gMjU1XTtcbiAgfVxuXG4gIGlmICh0eXBlb2Ygbm9ybS5iaWFzID09PSAnbnVtYmVyJykge1xuICAgIG5vcm1CaWFzID0gW25vcm0uYmlhcywgbm9ybS5iaWFzLCBub3JtLmJpYXMsIG5vcm0uYmlhc107XG4gIH0gZWxzZSB7XG4gICAgbm9ybUJpYXMgPSBbbm9ybS5iaWFzIVswXSwgbm9ybS5iaWFzIVsxXSwgbm9ybS5iaWFzIVsyXSwgbm9ybS5iaWFzIVszXSA/PyAwXTtcbiAgfVxuXG4gIGNvbnN0IGlucHV0Zm9ybWF0ID0gb3B0aW9ucy5mb3JtYXQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZm9ybWF0IDogJ1JHQkEnO1xuICAvLyBkZWZhdWx0IHZhbHVlIGlzIFJHQkEgc2luY2UgaW1hZ2VkYXRhIGFuZCBIVE1MSW1hZ2VFbGVtZW50IHVzZXMgaXRcblxuICBjb25zdCBvdXRwdXRmb3JtYXQgPVxuICAgIG9wdGlvbnMudGVuc29yRm9ybWF0ICE9PSB1bmRlZmluZWQgPyAob3B0aW9ucy50ZW5zb3JGb3JtYXQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMudGVuc29yRm9ybWF0IDogJ1JHQicpIDogJ1JHQic7XG4gIGNvbnN0IHN0cmlkZSA9IGhlaWdodCAqIHdpZHRoO1xuICBjb25zdCBmbG9hdDMyRGF0YSA9IG91dHB1dGZvcm1hdCA9PT0gJ1JHQkEnID8gbmV3IEZsb2F0MzJBcnJheShzdHJpZGUgKiA0KSA6IG5ldyBGbG9hdDMyQXJyYXkoc3RyaWRlICogMyk7XG5cbiAgLy8gRGVmYXVsdCBwb2ludGVyIGFzc2lnbm1lbnRzXG4gIGxldCBzdGVwID0gNCxcbiAgICBySW1hZ2VQb2ludGVyID0gMCxcbiAgICBnSW1hZ2VQb2ludGVyID0gMSxcbiAgICBiSW1hZ2VQb2ludGVyID0gMixcbiAgICBhSW1hZ2VQb2ludGVyID0gMztcbiAgbGV0IHJUZW5zb3JQb2ludGVyID0gMCxcbiAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZSxcbiAgICBiVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDIsXG4gICAgYVRlbnNvclBvaW50ZXIgPSAtMTtcblxuICAvLyBVcGRhdGluZyB0aGUgcG9pbnRlciBhc3NpZ25tZW50cyBiYXNlZCBvbiB0aGUgaW5wdXQgaW1hZ2UgZm9ybWF0XG4gIGlmIChpbnB1dGZvcm1hdCA9PT0gJ1JHQicpIHtcbiAgICBzdGVwID0gMztcbiAgICBySW1hZ2VQb2ludGVyID0gMDtcbiAgICBnSW1hZ2VQb2ludGVyID0gMTtcbiAgICBiSW1hZ2VQb2ludGVyID0gMjtcbiAgICBhSW1hZ2VQb2ludGVyID0gLTE7XG4gIH1cblxuICAvLyBVcGRhdGluZyB0aGUgcG9pbnRlciBhc3NpZ25tZW50cyBiYXNlZCBvbiB0aGUgb3V0cHV0IHRlbnNvciBmb3JtYXRcbiAgaWYgKG91dHB1dGZvcm1hdCA9PT0gJ1JHQkEnKSB7XG4gICAgYVRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAzO1xuICB9IGVsc2UgaWYgKG91dHB1dGZvcm1hdCA9PT0gJ1JCRycpIHtcbiAgICByVGVuc29yUG9pbnRlciA9IDA7XG4gICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGU7XG4gICAgZ1RlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyO1xuICB9IGVsc2UgaWYgKG91dHB1dGZvcm1hdCA9PT0gJ0JHUicpIHtcbiAgICBiVGVuc29yUG9pbnRlciA9IDA7XG4gICAgZ1RlbnNvclBvaW50ZXIgPSBzdHJpZGU7XG4gICAgclRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyO1xuICB9XG5cbiAgZm9yIChcbiAgICBsZXQgaSA9IDA7XG4gICAgaSA8IHN0cmlkZTtcbiAgICBpKyssIHJJbWFnZVBvaW50ZXIgKz0gc3RlcCwgYkltYWdlUG9pbnRlciArPSBzdGVwLCBnSW1hZ2VQb2ludGVyICs9IHN0ZXAsIGFJbWFnZVBvaW50ZXIgKz0gc3RlcFxuICApIHtcbiAgICBmbG9hdDMyRGF0YVtyVGVuc29yUG9pbnRlcisrXSA9IChidWZmZXJbckltYWdlUG9pbnRlcl0gKyBub3JtQmlhc1swXSkgLyBub3JtTWVhblswXTtcbiAgICBmbG9hdDMyRGF0YVtnVGVuc29yUG9pbnRlcisrXSA9IChidWZmZXJbZ0ltYWdlUG9pbnRlcl0gKyBub3JtQmlhc1sxXSkgLyBub3JtTWVhblsxXTtcbiAgICBmbG9hdDMyRGF0YVtiVGVuc29yUG9pbnRlcisrXSA9IChidWZmZXJbYkltYWdlUG9pbnRlcl0gKyBub3JtQmlhc1syXSkgLyBub3JtTWVhblsyXTtcbiAgICBpZiAoYVRlbnNvclBvaW50ZXIgIT09IC0xICYmIGFJbWFnZVBvaW50ZXIgIT09IC0xKSB7XG4gICAgICBmbG9hdDMyRGF0YVthVGVuc29yUG9pbnRlcisrXSA9IChidWZmZXJbYUltYWdlUG9pbnRlcl0gKyBub3JtQmlhc1szXSkgLyBub3JtTWVhblszXTtcbiAgICB9XG4gIH1cblxuICAvLyBGbG9hdDMyQXJyYXkgLT4gb3J0LlRlbnNvclxuICBjb25zdCBvdXRwdXRUZW5zb3IgPVxuICAgIG91dHB1dGZvcm1hdCA9PT0gJ1JHQkEnXG4gICAgICA/IG5ldyBUZW5zb3IoJ2Zsb2F0MzInLCBmbG9hdDMyRGF0YSwgWzEsIDQsIGhlaWdodCwgd2lkdGhdKVxuICAgICAgOiBuZXcgVGVuc29yKCdmbG9hdDMyJywgZmxvYXQzMkRhdGEsIFsxLCAzLCBoZWlnaHQsIHdpZHRoXSk7XG4gIHJldHVybiBvdXRwdXRUZW5zb3I7XG59O1xuXG4vKipcbiAqIGltcGxlbWVudGF0aW9uIG9mIFRlbnNvci5mcm9tSW1hZ2UoKS5cbiAqL1xuZXhwb3J0IGNvbnN0IHRlbnNvckZyb21JbWFnZSA9IGFzeW5jIChcbiAgaW1hZ2U6IEltYWdlRGF0YSB8IEhUTUxJbWFnZUVsZW1lbnQgfCBJbWFnZUJpdG1hcCB8IHN0cmluZyxcbiAgb3B0aW9ucz86XG4gICAgfCBUZW5zb3JGcm9tSW1hZ2VEYXRhT3B0aW9uc1xuICAgIHwgVGVuc29yRnJvbUltYWdlRWxlbWVudE9wdGlvbnNcbiAgICB8IFRlbnNvckZyb21JbWFnZUJpdG1hcE9wdGlvbnNcbiAgICB8IFRlbnNvckZyb21VcmxPcHRpb25zLFxuKTogUHJvbWlzZTxUZW5zb3I+ID0+IHtcbiAgLy8gY2hlY2tpbmcgdGhlIHR5cGUgb2YgaW1hZ2Ugb2JqZWN0XG4gIGNvbnN0IGlzSFRNTEltYWdlRWxlID0gdHlwZW9mIEhUTUxJbWFnZUVsZW1lbnQgIT09ICd1bmRlZmluZWQnICYmIGltYWdlIGluc3RhbmNlb2YgSFRNTEltYWdlRWxlbWVudDtcbiAgY29uc3QgaXNJbWFnZURhdGFFbGUgPSB0eXBlb2YgSW1hZ2VEYXRhICE9PSAndW5kZWZpbmVkJyAmJiBpbWFnZSBpbnN0YW5jZW9mIEltYWdlRGF0YTtcbiAgY29uc3QgaXNJbWFnZUJpdG1hcCA9IHR5cGVvZiBJbWFnZUJpdG1hcCAhPT0gJ3VuZGVmaW5lZCcgJiYgaW1hZ2UgaW5zdGFuY2VvZiBJbWFnZUJpdG1hcDtcbiAgY29uc3QgaXNTdHJpbmcgPSB0eXBlb2YgaW1hZ2UgPT09ICdzdHJpbmcnO1xuXG4gIGxldCBkYXRhOiBVaW50OENsYW1wZWRBcnJheSB8IHVuZGVmaW5lZDtcbiAgbGV0IGJ1ZmZlclRvVGVuc29yT3B0aW9uczogQnVmZmVyVG9UZW5zb3JPcHRpb25zID0gb3B0aW9ucyA/PyB7fTtcblxuICBjb25zdCBjcmVhdGVDYW52YXMgPSAoKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBPZmZzY3JlZW5DYW52YXMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gbmV3IE9mZnNjcmVlbkNhbnZhcygxLCAxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW52YXMgaXMgbm90IHN1cHBvcnRlZCcpO1xuICAgIH1cbiAgfTtcbiAgY29uc3QgY3JlYXRlQ2FudmFzQ29udGV4dCA9IChjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50IHwgT2Zmc2NyZWVuQ2FudmFzKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBIVE1MQ2FudmFzRWxlbWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgY2FudmFzIGluc3RhbmNlb2YgSFRNTENhbnZhc0VsZW1lbnQpIHtcbiAgICAgIHJldHVybiBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICB9IGVsc2UgaWYgKGNhbnZhcyBpbnN0YW5jZW9mIE9mZnNjcmVlbkNhbnZhcykge1xuICAgICAgcmV0dXJuIGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpIGFzIE9mZnNjcmVlbkNhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9O1xuICAvLyBmaWxsaW5nIGFuZCBjaGVja2luZyBpbWFnZSBjb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgaWYgKGlzSFRNTEltYWdlRWxlKSB7XG4gICAgLy8gSFRNTEltYWdlRWxlbWVudCAtIGltYWdlIG9iamVjdCAtIGZvcm1hdCBpcyBSR0JBIGJ5IGRlZmF1bHRcbiAgICBjb25zdCBjYW52YXMgPSBjcmVhdGVDYW52YXMoKTtcbiAgICBjYW52YXMud2lkdGggPSBpbWFnZS53aWR0aDtcbiAgICBjYW52YXMuaGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0O1xuICAgIGNvbnN0IHBpeGVsczJEQ29udGV4dCA9IGNyZWF0ZUNhbnZhc0NvbnRleHQoY2FudmFzKTtcblxuICAgIGlmIChwaXhlbHMyRENvbnRleHQgIT0gbnVsbCkge1xuICAgICAgbGV0IGhlaWdodCA9IGltYWdlLmhlaWdodDtcbiAgICAgIGxldCB3aWR0aCA9IGltYWdlLndpZHRoO1xuICAgICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLnJlc2l6ZWRIZWlnaHQgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLnJlc2l6ZWRXaWR0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGhlaWdodCA9IG9wdGlvbnMucmVzaXplZEhlaWdodDtcbiAgICAgICAgd2lkdGggPSBvcHRpb25zLnJlc2l6ZWRXaWR0aDtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMgPSBvcHRpb25zO1xuICAgICAgICBpZiAob3B0aW9ucy50ZW5zb3JGb3JtYXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgaW5wdXQgY29uZmlnIGZvcm1hdCBtdXN0IGJlIFJHQkEgZm9yIEhUTUxJbWFnZUVsZW1lbnQnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMudGVuc29yRm9ybWF0ID0gJ1JHQkEnO1xuICAgICAgICB9XG4gICAgICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy53aWR0aCA9IHdpZHRoO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLnRlbnNvckZvcm1hdCA9ICdSR0JBJztcbiAgICAgICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLndpZHRoID0gd2lkdGg7XG4gICAgICB9XG5cbiAgICAgIHBpeGVsczJEQ29udGV4dC5kcmF3SW1hZ2UoaW1hZ2UsIDAsIDApO1xuICAgICAgZGF0YSA9IHBpeGVsczJEQ29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgd2lkdGgsIGhlaWdodCkuZGF0YTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhJyk7XG4gICAgfVxuICB9IGVsc2UgaWYgKGlzSW1hZ2VEYXRhRWxlKSB7XG4gICAgbGV0IGhlaWdodDogbnVtYmVyO1xuICAgIGxldCB3aWR0aDogbnVtYmVyO1xuXG4gICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLnJlc2l6ZWRXaWR0aCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMucmVzaXplZEhlaWdodCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBoZWlnaHQgPSBvcHRpb25zLnJlc2l6ZWRIZWlnaHQ7XG4gICAgICB3aWR0aCA9IG9wdGlvbnMucmVzaXplZFdpZHRoO1xuICAgIH0gZWxzZSB7XG4gICAgICBoZWlnaHQgPSBpbWFnZS5oZWlnaHQ7XG4gICAgICB3aWR0aCA9IGltYWdlLndpZHRoO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgfVxuICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy5mb3JtYXQgPSAnUkdCQSc7XG4gICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLmhlaWdodCA9IGhlaWdodDtcbiAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMud2lkdGggPSB3aWR0aDtcblxuICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IHRlbXBDYW52YXMgPSBjcmVhdGVDYW52YXMoKTtcblxuICAgICAgdGVtcENhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgICAgdGVtcENhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICAgIGNvbnN0IHBpeGVsczJEQ29udGV4dCA9IGNyZWF0ZUNhbnZhc0NvbnRleHQodGVtcENhbnZhcyk7XG5cbiAgICAgIGlmIChwaXhlbHMyRENvbnRleHQgIT0gbnVsbCkge1xuICAgICAgICBwaXhlbHMyRENvbnRleHQucHV0SW1hZ2VEYXRhKGltYWdlLCAwLCAwKTtcbiAgICAgICAgZGF0YSA9IHBpeGVsczJEQ29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgd2lkdGgsIGhlaWdodCkuZGF0YTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBhY2Nlc3MgaW1hZ2UgZGF0YScpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBkYXRhID0gaW1hZ2UuZGF0YTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoaXNJbWFnZUJpdG1hcCkge1xuICAgIC8vIEltYWdlQml0bWFwIC0gaW1hZ2Ugb2JqZWN0IC0gZm9ybWF0IG11c3QgYmUgcHJvdmlkZWQgYnkgdXNlclxuICAgIGlmIChvcHRpb25zID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUGxlYXNlIHByb3ZpZGUgaW1hZ2UgY29uZmlnIHdpdGggZm9ybWF0IGZvciBJbWFnZWJpdG1hcCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGNhbnZhcyA9IGNyZWF0ZUNhbnZhcygpO1xuICAgIGNhbnZhcy53aWR0aCA9IGltYWdlLndpZHRoO1xuICAgIGNhbnZhcy5oZWlnaHQgPSBpbWFnZS5oZWlnaHQ7XG4gICAgY29uc3QgcGl4ZWxzMkRDb250ZXh0ID0gY3JlYXRlQ2FudmFzQ29udGV4dChjYW52YXMpO1xuXG4gICAgaWYgKHBpeGVsczJEQ29udGV4dCAhPSBudWxsKSB7XG4gICAgICBjb25zdCBoZWlnaHQgPSBpbWFnZS5oZWlnaHQ7XG4gICAgICBjb25zdCB3aWR0aCA9IGltYWdlLndpZHRoO1xuICAgICAgcGl4ZWxzMkRDb250ZXh0LmRyYXdJbWFnZShpbWFnZSwgMCwgMCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICBkYXRhID0gcGl4ZWxzMkRDb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCB3aWR0aCwgaGVpZ2h0KS5kYXRhO1xuICAgICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLmhlaWdodCA9IGhlaWdodDtcbiAgICAgIGJ1ZmZlclRvVGVuc29yT3B0aW9ucy53aWR0aCA9IHdpZHRoO1xuICAgICAgcmV0dXJuIGJ1ZmZlclRvVGVuc29yKGRhdGEsIGJ1ZmZlclRvVGVuc29yT3B0aW9ucyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBhY2Nlc3MgaW1hZ2UgZGF0YScpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChpc1N0cmluZykge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBjYW52YXMgPSBjcmVhdGVDYW52YXMoKTtcbiAgICAgIGNvbnN0IGNvbnRleHQgPSBjcmVhdGVDYW52YXNDb250ZXh0KGNhbnZhcyk7XG4gICAgICBpZiAoIWltYWdlIHx8ICFjb250ZXh0KSB7XG4gICAgICAgIHJldHVybiByZWplY3QoKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG5ld0ltYWdlID0gbmV3IEltYWdlKCk7XG4gICAgICBuZXdJbWFnZS5jcm9zc09yaWdpbiA9ICdBbm9ueW1vdXMnO1xuICAgICAgbmV3SW1hZ2Uuc3JjID0gaW1hZ2U7XG4gICAgICBuZXdJbWFnZS5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgIGNhbnZhcy53aWR0aCA9IG5ld0ltYWdlLndpZHRoO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gbmV3SW1hZ2UuaGVpZ2h0O1xuICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShuZXdJbWFnZSwgMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgICAgY29uc3QgaW1nID0gY29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcblxuICAgICAgICBidWZmZXJUb1RlbnNvck9wdGlvbnMuaGVpZ2h0ID0gY2FudmFzLmhlaWdodDtcbiAgICAgICAgYnVmZmVyVG9UZW5zb3JPcHRpb25zLndpZHRoID0gY2FudmFzLndpZHRoO1xuICAgICAgICByZXNvbHZlKGJ1ZmZlclRvVGVuc29yKGltZy5kYXRhLCBidWZmZXJUb1RlbnNvck9wdGlvbnMpKTtcbiAgICAgIH07XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBkYXRhIHByb3ZpZGVkIGlzIG5vdCBzdXBwb3J0ZWQgLSBhYm9ydGVkIHRlbnNvciBjcmVhdGlvbicpO1xuICB9XG5cbiAgaWYgKGRhdGEgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBidWZmZXJUb1RlbnNvcihkYXRhLCBidWZmZXJUb1RlbnNvck9wdGlvbnMpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgZGF0YSBwcm92aWRlZCBpcyBub3Qgc3VwcG9ydGVkIC0gYWJvcnRlZCB0ZW5zb3IgY3JlYXRpb24nKTtcbiAgfVxufTtcblxuLyoqXG4gKiBpbXBsZW1lbnRhdGlvbiBvZiBUZW5zb3IuZnJvbVRleHR1cmUoKS5cbiAqL1xuZXhwb3J0IGNvbnN0IHRlbnNvckZyb21UZXh0dXJlID0gPFQgZXh0ZW5kcyBUZW5zb3JJbnRlcmZhY2UuVGV4dHVyZURhdGFUeXBlcz4oXG4gIHRleHR1cmU6IFRlbnNvckludGVyZmFjZS5UZXh0dXJlVHlwZSxcbiAgb3B0aW9uczogVGVuc29yRnJvbVRleHR1cmVPcHRpb25zPFQ+LFxuKTogVGVuc29yID0+IHtcbiAgY29uc3QgeyB3aWR0aCwgaGVpZ2h0LCBkb3dubG9hZCwgZGlzcG9zZSB9ID0gb3B0aW9ucztcbiAgLy8gQWx3YXlzIGFzc3VtZSBSR0JBRjMyLiBUT0RPOiBzdXBwb3J0IGRpZmZlcmVudCB0ZXh0dXJlIGZvcm1hdFxuICBjb25zdCBkaW1zID0gWzEsIGhlaWdodCwgd2lkdGgsIDRdO1xuICByZXR1cm4gbmV3IFRlbnNvcih7IGxvY2F0aW9uOiAndGV4dHVyZScsIHR5cGU6ICdmbG9hdDMyJywgdGV4dHVyZSwgZGltcywgZG93bmxvYWQsIGRpc3Bvc2UgfSk7XG59O1xuXG4vKipcbiAqIGltcGxlbWVudGF0aW9uIG9mIFRlbnNvci5mcm9tR3B1QnVmZmVyKCkuXG4gKi9cbmV4cG9ydCBjb25zdCB0ZW5zb3JGcm9tR3B1QnVmZmVyID0gPFQgZXh0ZW5kcyBUZW5zb3JJbnRlcmZhY2UuR3B1QnVmZmVyRGF0YVR5cGVzPihcbiAgZ3B1QnVmZmVyOiBUZW5zb3JJbnRlcmZhY2UuR3B1QnVmZmVyVHlwZSxcbiAgb3B0aW9uczogVGVuc29yRnJvbUdwdUJ1ZmZlck9wdGlvbnM8VD4sXG4pOiBUZW5zb3IgPT4ge1xuICBjb25zdCB7IGRhdGFUeXBlLCBkaW1zLCBkb3dubG9hZCwgZGlzcG9zZSB9ID0gb3B0aW9ucztcbiAgcmV0dXJuIG5ldyBUZW5zb3IoeyBsb2NhdGlvbjogJ2dwdS1idWZmZXInLCB0eXBlOiBkYXRhVHlwZSA/PyAnZmxvYXQzMicsIGdwdUJ1ZmZlciwgZGltcywgZG93bmxvYWQsIGRpc3Bvc2UgfSk7XG59O1xuXG4vKipcbiAqIGltcGxlbWVudGF0aW9uIG9mIFRlbnNvci5mcm9tTUxUZW5zb3IoKS5cbiAqL1xuZXhwb3J0IGNvbnN0IHRlbnNvckZyb21NTFRlbnNvciA9IDxUIGV4dGVuZHMgVGVuc29ySW50ZXJmYWNlLk1MVGVuc29yRGF0YVR5cGVzPihcbiAgbWxUZW5zb3I6IFRlbnNvckludGVyZmFjZS5NTFRlbnNvclR5cGUsXG4gIG9wdGlvbnM6IFRlbnNvckZyb21NTFRlbnNvck9wdGlvbnM8VD4sXG4pOiBUZW5zb3IgPT4ge1xuICBjb25zdCB7IGRhdGFUeXBlLCBkaW1zLCBkb3dubG9hZCwgZGlzcG9zZSB9ID0gb3B0aW9ucztcbiAgcmV0dXJuIG5ldyBUZW5zb3IoeyBsb2NhdGlvbjogJ21sLXRlbnNvcicsIHR5cGU6IGRhdGFUeXBlID8/ICdmbG9hdDMyJywgbWxUZW5zb3IsIGRpbXMsIGRvd25sb2FkLCBkaXNwb3NlIH0pO1xufTtcblxuLyoqXG4gKiBpbXBsZW1lbnRhdGlvbiBvZiBUZW5zb3IuZnJvbVBpbm5lZEJ1ZmZlcigpLlxuICovXG5leHBvcnQgY29uc3QgdGVuc29yRnJvbVBpbm5lZEJ1ZmZlciA9IDxUIGV4dGVuZHMgVGVuc29ySW50ZXJmYWNlLkNwdVBpbm5lZERhdGFUeXBlcz4oXG4gIHR5cGU6IFQsXG4gIGJ1ZmZlcjogVGVuc29ySW50ZXJmYWNlLkRhdGFUeXBlTWFwW1RdLFxuICBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10sXG4pOiBUZW5zb3IgPT4gbmV3IFRlbnNvcih7IGxvY2F0aW9uOiAnY3B1LXBpbm5lZCcsIHR5cGUsIGRhdGE6IGJ1ZmZlciwgZGltczogZGltcyA/PyBbYnVmZmVyLmxlbmd0aF0gfSk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJy4vdGVuc29yLmpzJztcblxuZXhwb3J0IHR5cGUgU3VwcG9ydGVkVHlwZWRBcnJheUNvbnN0cnVjdG9ycyA9XG4gIHwgRmxvYXQzMkFycmF5Q29uc3RydWN0b3JcbiAgfCBVaW50OEFycmF5Q29uc3RydWN0b3JcbiAgfCBJbnQ4QXJyYXlDb25zdHJ1Y3RvclxuICB8IFVpbnQxNkFycmF5Q29uc3RydWN0b3JcbiAgfCBJbnQxNkFycmF5Q29uc3RydWN0b3JcbiAgfCBJbnQzMkFycmF5Q29uc3RydWN0b3JcbiAgfCBCaWdJbnQ2NEFycmF5Q29uc3RydWN0b3JcbiAgfCBVaW50OEFycmF5Q29uc3RydWN0b3JcbiAgfCBGbG9hdDY0QXJyYXlDb25zdHJ1Y3RvclxuICB8IFVpbnQzMkFycmF5Q29uc3RydWN0b3JcbiAgfCBCaWdVaW50NjRBcnJheUNvbnN0cnVjdG9yO1xuZXhwb3J0IHR5cGUgU3VwcG9ydGVkVHlwZWRBcnJheSA9IEluc3RhbmNlVHlwZTxTdXBwb3J0ZWRUeXBlZEFycmF5Q29uc3RydWN0b3JzPjtcblxuLy8gYSBydW50aW1lIG1hcCB0aGF0IG1hcHMgdHlwZSBzdHJpbmcgdG8gVHlwZWRBcnJheSBjb25zdHJ1Y3Rvci4gU2hvdWxkIG1hdGNoIFRlbnNvci5EYXRhVHlwZU1hcC5cbmV4cG9ydCBjb25zdCBOVU1FUklDX1RFTlNPUl9UWVBFX1RPX1RZUEVEQVJSQVlfTUFQID0gbmV3IE1hcDxzdHJpbmcsIFN1cHBvcnRlZFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnM+KFtcbiAgWydmbG9hdDMyJywgRmxvYXQzMkFycmF5XSxcbiAgWyd1aW50OCcsIFVpbnQ4QXJyYXldLFxuICBbJ2ludDgnLCBJbnQ4QXJyYXldLFxuICBbJ3VpbnQxNicsIFVpbnQxNkFycmF5XSxcbiAgWydpbnQxNicsIEludDE2QXJyYXldLFxuICBbJ2ludDMyJywgSW50MzJBcnJheV0sXG4gIFsnYm9vbCcsIFVpbnQ4QXJyYXldLFxuICBbJ2Zsb2F0NjQnLCBGbG9hdDY0QXJyYXldLFxuICBbJ3VpbnQzMicsIFVpbnQzMkFycmF5XSxcbiAgWydpbnQ0JywgVWludDhBcnJheV0sXG4gIFsndWludDQnLCBVaW50OEFycmF5XSxcbl0pO1xuXG4vLyBhIHJ1bnRpbWUgbWFwIHRoYXQgbWFwcyB0eXBlIHN0cmluZyB0byBUeXBlZEFycmF5IGNvbnN0cnVjdG9yLiBTaG91bGQgbWF0Y2ggVGVuc29yLkRhdGFUeXBlTWFwLlxuZXhwb3J0IGNvbnN0IE5VTUVSSUNfVEVOU09SX1RZUEVEQVJSQVlfVE9fVFlQRV9NQVAgPSBuZXcgTWFwPFN1cHBvcnRlZFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnMsIFRlbnNvci5UeXBlPihbXG4gIFtGbG9hdDMyQXJyYXksICdmbG9hdDMyJ10sXG4gIFtVaW50OEFycmF5LCAndWludDgnXSxcbiAgW0ludDhBcnJheSwgJ2ludDgnXSxcbiAgW1VpbnQxNkFycmF5LCAndWludDE2J10sXG4gIFtJbnQxNkFycmF5LCAnaW50MTYnXSxcbiAgW0ludDMyQXJyYXksICdpbnQzMiddLFxuICBbRmxvYXQ2NEFycmF5LCAnZmxvYXQ2NCddLFxuICBbVWludDMyQXJyYXksICd1aW50MzInXSxcbl0pO1xuXG4vLyB0aGUgZm9sbG93aW5nIGNvZGUgYWxsb3dzIGRlbGF5aW5nIGV4ZWN1dGlvbiBvZiBCaWdJbnQvRmxvYXQxNkFycmF5IGNoZWNraW5nLiBUaGlzIGFsbG93cyBsYXp5IGluaXRpYWxpemF0aW9uIGZvclxuLy8gTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUCBhbmQgTlVNRVJJQ19URU5TT1JfVFlQRURBUlJBWV9UT19UWVBFX01BUCwgd2hpY2ggYWxsb3dzIEJpZ0ludC9GbG9hdDE2QXJyYXlcbi8vIHBvbHlmaWxsIGlmIGF2YWlsYWJsZS5cbmxldCBpc1R5cGVkQXJyYXlDaGVja2VkID0gZmFsc2U7XG5leHBvcnQgY29uc3QgY2hlY2tUeXBlZEFycmF5ID0gKCkgPT4ge1xuICBpZiAoIWlzVHlwZWRBcnJheUNoZWNrZWQpIHtcbiAgICBpc1R5cGVkQXJyYXlDaGVja2VkID0gdHJ1ZTtcbiAgICBjb25zdCBpc0JpZ0ludDY0QXJyYXlBdmFpbGFibGUgPSB0eXBlb2YgQmlnSW50NjRBcnJheSAhPT0gJ3VuZGVmaW5lZCcgJiYgQmlnSW50NjRBcnJheS5mcm9tO1xuICAgIGNvbnN0IGlzQmlnVWludDY0QXJyYXlBdmFpbGFibGUgPSB0eXBlb2YgQmlnVWludDY0QXJyYXkgIT09ICd1bmRlZmluZWQnICYmIEJpZ1VpbnQ2NEFycmF5LmZyb207XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgY29uc3QgRmxvYXQxNkFycmF5ID0gKGdsb2JhbFRoaXMgYXMgYW55KS5GbG9hdDE2QXJyYXk7XG4gICAgY29uc3QgaXNGbG9hdDE2QXJyYXlBdmFpbGFibGUgPSB0eXBlb2YgRmxvYXQxNkFycmF5ICE9PSAndW5kZWZpbmVkJyAmJiBGbG9hdDE2QXJyYXkuZnJvbTtcblxuICAgIGlmIChpc0JpZ0ludDY0QXJyYXlBdmFpbGFibGUpIHtcbiAgICAgIE5VTUVSSUNfVEVOU09SX1RZUEVfVE9fVFlQRURBUlJBWV9NQVAuc2V0KCdpbnQ2NCcsIEJpZ0ludDY0QXJyYXkpO1xuICAgICAgTlVNRVJJQ19URU5TT1JfVFlQRURBUlJBWV9UT19UWVBFX01BUC5zZXQoQmlnSW50NjRBcnJheSwgJ2ludDY0Jyk7XG4gICAgfVxuICAgIGlmIChpc0JpZ1VpbnQ2NEFycmF5QXZhaWxhYmxlKSB7XG4gICAgICBOVU1FUklDX1RFTlNPUl9UWVBFX1RPX1RZUEVEQVJSQVlfTUFQLnNldCgndWludDY0JywgQmlnVWludDY0QXJyYXkpO1xuICAgICAgTlVNRVJJQ19URU5TT1JfVFlQRURBUlJBWV9UT19UWVBFX01BUC5zZXQoQmlnVWludDY0QXJyYXksICd1aW50NjQnKTtcbiAgICB9XG4gICAgaWYgKGlzRmxvYXQxNkFycmF5QXZhaWxhYmxlKSB7XG4gICAgICBOVU1FUklDX1RFTlNPUl9UWVBFX1RPX1RZUEVEQVJSQVlfTUFQLnNldCgnZmxvYXQxNicsIEZsb2F0MTZBcnJheSk7XG4gICAgICBOVU1FUklDX1RFTlNPUl9UWVBFREFSUkFZX1RPX1RZUEVfTUFQLnNldChGbG9hdDE2QXJyYXksICdmbG9hdDE2Jyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGlmIEZsb2F0MTZBcnJheSBpcyBub3QgYXZhaWxhYmxlLCB1c2UgJ1VpbnQxNkFycmF5JyB0byBzdG9yZSB0aGUgZGF0YS5cbiAgICAgIE5VTUVSSUNfVEVOU09SX1RZUEVfVE9fVFlQRURBUlJBWV9NQVAuc2V0KCdmbG9hdDE2JywgVWludDE2QXJyYXkpO1xuICAgIH1cbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtcbiAgQ3B1UGlubmVkQ29uc3RydWN0b3JQYXJhbWV0ZXJzLFxuICBHcHVCdWZmZXJDb25zdHJ1Y3RvclBhcmFtZXRlcnMsXG4gIE1MVGVuc29yQ29uc3RydWN0b3JQYXJhbWV0ZXJzLFxuICBUZXh0dXJlQ29uc3RydWN0b3JQYXJhbWV0ZXJzLFxufSBmcm9tICcuL3RlbnNvci1mYWN0b3J5LmpzJztcbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJy4vdGVuc29yLWltcGwuanMnO1xuXG4vKipcbiAqIGNhbGN1bGF0ZSBzaXplIGZyb20gZGltcy5cbiAqXG4gKiBAcGFyYW0gZGltcyB0aGUgZGltcyBhcnJheS4gTWF5IGJlIGFuIGlsbGVnYWwgaW5wdXQuXG4gKi9cbmV4cG9ydCBjb25zdCBjYWxjdWxhdGVTaXplID0gKGRpbXM6IHJlYWRvbmx5IHVua25vd25bXSk6IG51bWJlciA9PiB7XG4gIGxldCBzaXplID0gMTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgZGltID0gZGltc1tpXTtcbiAgICBpZiAodHlwZW9mIGRpbSAhPT0gJ251bWJlcicgfHwgIU51bWJlci5pc1NhZmVJbnRlZ2VyKGRpbSkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYGRpbXNbJHtpfV0gbXVzdCBiZSBhbiBpbnRlZ2VyLCBnb3Q6ICR7ZGltfWApO1xuICAgIH1cbiAgICBpZiAoZGltIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoYGRpbXNbJHtpfV0gbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyLCBnb3Q6ICR7ZGltfWApO1xuICAgIH1cbiAgICBzaXplICo9IGRpbTtcbiAgfVxuICByZXR1cm4gc2l6ZTtcbn07XG5cbi8qKlxuICogaW1wbGVtZW50YXRpb24gb2YgVGVuc29yLnJlc2hhcGUoKVxuICovXG5leHBvcnQgY29uc3QgdGVuc29yUmVzaGFwZSA9ICh0ZW5zb3I6IFRlbnNvciwgZGltczogcmVhZG9ubHkgbnVtYmVyW10pOiBUZW5zb3IgPT4ge1xuICBzd2l0Y2ggKHRlbnNvci5sb2NhdGlvbikge1xuICAgIGNhc2UgJ2NwdSc6XG4gICAgICByZXR1cm4gbmV3IFRlbnNvcih0ZW5zb3IudHlwZSwgdGVuc29yLmRhdGEsIGRpbXMpO1xuICAgIGNhc2UgJ2NwdS1waW5uZWQnOlxuICAgICAgcmV0dXJuIG5ldyBUZW5zb3Ioe1xuICAgICAgICBsb2NhdGlvbjogJ2NwdS1waW5uZWQnLFxuICAgICAgICBkYXRhOiB0ZW5zb3IuZGF0YSBhcyBDcHVQaW5uZWRDb25zdHJ1Y3RvclBhcmFtZXRlcnNbJ2RhdGEnXSxcbiAgICAgICAgdHlwZTogdGVuc29yLnR5cGUgYXMgQ3B1UGlubmVkQ29uc3RydWN0b3JQYXJhbWV0ZXJzWyd0eXBlJ10sXG4gICAgICAgIGRpbXMsXG4gICAgICB9KTtcbiAgICBjYXNlICd0ZXh0dXJlJzpcbiAgICAgIHJldHVybiBuZXcgVGVuc29yKHtcbiAgICAgICAgbG9jYXRpb246ICd0ZXh0dXJlJyxcbiAgICAgICAgdGV4dHVyZTogdGVuc29yLnRleHR1cmUsXG4gICAgICAgIHR5cGU6IHRlbnNvci50eXBlIGFzIFRleHR1cmVDb25zdHJ1Y3RvclBhcmFtZXRlcnNbJ3R5cGUnXSxcbiAgICAgICAgZGltcyxcbiAgICAgIH0pO1xuICAgIGNhc2UgJ2dwdS1idWZmZXInOlxuICAgICAgcmV0dXJuIG5ldyBUZW5zb3Ioe1xuICAgICAgICBsb2NhdGlvbjogJ2dwdS1idWZmZXInLFxuICAgICAgICBncHVCdWZmZXI6IHRlbnNvci5ncHVCdWZmZXIsXG4gICAgICAgIHR5cGU6IHRlbnNvci50eXBlIGFzIEdwdUJ1ZmZlckNvbnN0cnVjdG9yUGFyYW1ldGVyc1sndHlwZSddLFxuICAgICAgICBkaW1zLFxuICAgICAgfSk7XG4gICAgY2FzZSAnbWwtdGVuc29yJzpcbiAgICAgIHJldHVybiBuZXcgVGVuc29yKHtcbiAgICAgICAgbG9jYXRpb246ICdtbC10ZW5zb3InLFxuICAgICAgICBtbFRlbnNvcjogdGVuc29yLm1sVGVuc29yLFxuICAgICAgICB0eXBlOiB0ZW5zb3IudHlwZSBhcyBNTFRlbnNvckNvbnN0cnVjdG9yUGFyYW1ldGVyc1sndHlwZSddLFxuICAgICAgICBkaW1zLFxuICAgICAgfSk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdGVuc29yUmVzaGFwZTogdGVuc29yIGxvY2F0aW9uICR7dGVuc29yLmxvY2F0aW9ufSBpcyBub3Qgc3VwcG9ydGVkYCk7XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IHRlbnNvclRvRGF0YVVSTCwgdGVuc29yVG9JbWFnZURhdGEgfSBmcm9tICcuL3RlbnNvci1jb252ZXJzaW9uLWltcGwuanMnO1xuaW1wb3J0IHsgVGVuc29yVG9EYXRhVXJsT3B0aW9ucywgVGVuc29yVG9JbWFnZURhdGFPcHRpb25zIH0gZnJvbSAnLi90ZW5zb3ItY29udmVyc2lvbi5qcyc7XG5pbXBvcnQge1xuICB0ZW5zb3JGcm9tR3B1QnVmZmVyLFxuICB0ZW5zb3JGcm9tSW1hZ2UsXG4gIHRlbnNvckZyb21NTFRlbnNvcixcbiAgdGVuc29yRnJvbVBpbm5lZEJ1ZmZlcixcbiAgdGVuc29yRnJvbVRleHR1cmUsXG59IGZyb20gJy4vdGVuc29yLWZhY3RvcnktaW1wbC5qcyc7XG5pbXBvcnQge1xuICBDcHVQaW5uZWRDb25zdHJ1Y3RvclBhcmFtZXRlcnMsXG4gIEdwdUJ1ZmZlckNvbnN0cnVjdG9yUGFyYW1ldGVycyxcbiAgTUxUZW5zb3JDb25zdHJ1Y3RvclBhcmFtZXRlcnMsXG4gIFRlbnNvckZyb21HcHVCdWZmZXJPcHRpb25zLFxuICBUZW5zb3JGcm9tSW1hZ2VCaXRtYXBPcHRpb25zLFxuICBUZW5zb3JGcm9tSW1hZ2VEYXRhT3B0aW9ucyxcbiAgVGVuc29yRnJvbUltYWdlRWxlbWVudE9wdGlvbnMsXG4gIFRlbnNvckZyb21NTFRlbnNvck9wdGlvbnMsXG4gIFRlbnNvckZyb21UZXh0dXJlT3B0aW9ucyxcbiAgVGVuc29yRnJvbVVybE9wdGlvbnMsXG4gIFRleHR1cmVDb25zdHJ1Y3RvclBhcmFtZXRlcnMsXG59IGZyb20gJy4vdGVuc29yLWZhY3RvcnkuanMnO1xuaW1wb3J0IHtcbiAgY2hlY2tUeXBlZEFycmF5LFxuICBOVU1FUklDX1RFTlNPUl9UWVBFX1RPX1RZUEVEQVJSQVlfTUFQLFxuICBOVU1FUklDX1RFTlNPUl9UWVBFREFSUkFZX1RPX1RZUEVfTUFQLFxuICBTdXBwb3J0ZWRUeXBlZEFycmF5LFxuICBTdXBwb3J0ZWRUeXBlZEFycmF5Q29uc3RydWN0b3JzLFxufSBmcm9tICcuL3RlbnNvci1pbXBsLXR5cGUtbWFwcGluZy5qcyc7XG5pbXBvcnQgeyBjYWxjdWxhdGVTaXplLCB0ZW5zb3JSZXNoYXBlIH0gZnJvbSAnLi90ZW5zb3ItdXRpbHMtaW1wbC5qcyc7XG5pbXBvcnQgeyBUZW5zb3IgYXMgVGVuc29ySW50ZXJmYWNlIH0gZnJvbSAnLi90ZW5zb3IuanMnO1xuXG4vLyB0eXBlIGFsaWFzZXMgZm9yIHRob3NlIGV4cG9ydGVkIGZyb20gVGVuc29yIGludGVyZmFjZVxuXG50eXBlIFRlbnNvclR5cGUgPSBUZW5zb3JJbnRlcmZhY2UuVHlwZTtcbnR5cGUgVGVuc29yRGF0YVR5cGUgPSBUZW5zb3JJbnRlcmZhY2UuRGF0YVR5cGU7XG50eXBlIFRlbnNvckRhdGFMb2NhdGlvbiA9IFRlbnNvckludGVyZmFjZS5EYXRhTG9jYXRpb247XG50eXBlIFRlbnNvclRleHR1cmVUeXBlID0gVGVuc29ySW50ZXJmYWNlLlRleHR1cmVUeXBlO1xudHlwZSBUZW5zb3JHcHVCdWZmZXJUeXBlID0gVGVuc29ySW50ZXJmYWNlLkdwdUJ1ZmZlclR5cGU7XG50eXBlIFRlbnNvck1MVGVuc29yVHlwZSA9IFRlbnNvckludGVyZmFjZS5NTFRlbnNvclR5cGU7XG5cbi8qKlxuICogdGhlIGltcGxlbWVudGF0aW9uIG9mIFRlbnNvciBpbnRlcmZhY2UuXG4gKlxuICogQGlnbm9yZVxuICovXG5leHBvcnQgY2xhc3MgVGVuc29yIGltcGxlbWVudHMgVGVuc29ySW50ZXJmYWNlIHtcbiAgLy8gI3JlZ2lvbiBjb25zdHJ1Y3RvcnNcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IENQVSB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIHR5cGUsIGRhdGEgYW5kIGRpbXMuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICB0eXBlOiBUZW5zb3JUeXBlLFxuICAgIGRhdGE6IFRlbnNvckRhdGFUeXBlIHwgVWludDhDbGFtcGVkQXJyYXkgfCByZWFkb25seSBzdHJpbmdbXSB8IHJlYWRvbmx5IG51bWJlcltdIHwgcmVhZG9ubHkgYm9vbGVhbltdLFxuICAgIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSxcbiAgKTtcbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBDUFUgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLiBUeXBlIGlzIGluZmVycmVkIGZyb20gZGF0YS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIGRhdGE6IFRlbnNvckRhdGFUeXBlIHwgVWludDhDbGFtcGVkQXJyYXkgfCByZWFkb25seSBzdHJpbmdbXSB8IHJlYWRvbmx5IGJvb2xlYW5bXSxcbiAgICBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10sXG4gICk7XG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBwaW5uZWQgQ1BVIGRhdGEgd2l0aCB0aGUgZ2l2ZW4gdHlwZSBhbmQgZGltcy5cbiAgICpcbiAgICogVGVuc29yJ3MgbG9jYXRpb24gd2lsbCBiZSBzZXQgdG8gJ2NwdS1waW5uZWQnLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gU3BlY2lmeSB0aGUgcGFyYW1ldGVycyB0byBjb25zdHJ1Y3QgdGhlIHRlbnNvci5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHBhcmFtczogQ3B1UGlubmVkQ29uc3RydWN0b3JQYXJhbWV0ZXJzKTtcbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIFdlYkdMIHRleHR1cmUgd2l0aCB0aGUgZ2l2ZW4gdHlwZSBhbmQgZGltcy5cbiAgICpcbiAgICogVGVuc29yJ3MgbG9jYXRpb24gd2lsbCBiZSBzZXQgdG8gJ3RleHR1cmUnLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gU3BlY2lmeSB0aGUgcGFyYW1ldGVycyB0byBjb25zdHJ1Y3QgdGhlIHRlbnNvci5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHBhcmFtczogVGV4dHVyZUNvbnN0cnVjdG9yUGFyYW1ldGVycyk7XG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBXZWJHUFUgYnVmZmVyIHdpdGggdGhlIGdpdmVuIHR5cGUgYW5kIGRpbXMuXG4gICAqXG4gICAqIFRlbnNvcidzIGxvY2F0aW9uIHdpbGwgYmUgc2V0IHRvICdncHUtYnVmZmVyJy5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyAtIFNwZWNpZnkgdGhlIHBhcmFtZXRlcnMgdG8gY29uc3RydWN0IHRoZSB0ZW5zb3IuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihwYXJhbXM6IEdwdUJ1ZmZlckNvbnN0cnVjdG9yUGFyYW1ldGVycyk7XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIFdlYk5OIE1MVGVuc29yIHdpdGggdGhlIGdpdmVuIHR5cGUgYW5kIGRpbXMuXG4gICAqXG4gICAqIFRlbnNvcidzIGxvY2F0aW9uIHdpbGwgYmUgc2V0IHRvICdtbC10ZW5zb3InLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gU3BlY2lmeSB0aGUgcGFyYW1ldGVycyB0byBjb25zdHJ1Y3QgdGhlIHRlbnNvci5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHBhcmFtczogTUxUZW5zb3JDb25zdHJ1Y3RvclBhcmFtZXRlcnMpO1xuXG4gIC8qKlxuICAgKiBpbXBsZW1lbnRhdGlvbi5cbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIGFyZzA6XG4gICAgICB8IFRlbnNvclR5cGVcbiAgICAgIHwgVGVuc29yRGF0YVR5cGVcbiAgICAgIHwgVWludDhDbGFtcGVkQXJyYXlcbiAgICAgIHwgcmVhZG9ubHkgc3RyaW5nW11cbiAgICAgIHwgcmVhZG9ubHkgYm9vbGVhbltdXG4gICAgICB8IENwdVBpbm5lZENvbnN0cnVjdG9yUGFyYW1ldGVyc1xuICAgICAgfCBUZXh0dXJlQ29uc3RydWN0b3JQYXJhbWV0ZXJzXG4gICAgICB8IEdwdUJ1ZmZlckNvbnN0cnVjdG9yUGFyYW1ldGVyc1xuICAgICAgfCBNTFRlbnNvckNvbnN0cnVjdG9yUGFyYW1ldGVycyxcbiAgICBhcmcxPzogVGVuc29yRGF0YVR5cGUgfCBVaW50OENsYW1wZWRBcnJheSB8IHJlYWRvbmx5IG51bWJlcltdIHwgcmVhZG9ubHkgc3RyaW5nW10gfCByZWFkb25seSBib29sZWFuW10sXG4gICAgYXJnMj86IHJlYWRvbmx5IG51bWJlcltdLFxuICApIHtcbiAgICAvLyBwZXJmb3JtIG9uZS10aW1lIGNoZWNrIGZvciBCaWdJbnQvRmxvYXQxNkFycmF5IHN1cHBvcnRcbiAgICBjaGVja1R5cGVkQXJyYXkoKTtcblxuICAgIGxldCB0eXBlOiBUZW5zb3JUeXBlO1xuICAgIGxldCBkaW1zOiByZWFkb25seSBudW1iZXJbXTtcblxuICAgIGlmICh0eXBlb2YgYXJnMCA9PT0gJ29iamVjdCcgJiYgJ2xvY2F0aW9uJyBpbiBhcmcwKSB7XG4gICAgICAvL1xuICAgICAgLy8gY29uc3RydWN0aW5nIHRlbnNvciBmcm9tIHNwZWNpZmljIGxvY2F0aW9uXG4gICAgICAvL1xuICAgICAgdGhpcy5kYXRhTG9jYXRpb24gPSBhcmcwLmxvY2F0aW9uO1xuICAgICAgdHlwZSA9IGFyZzAudHlwZTtcbiAgICAgIGRpbXMgPSBhcmcwLmRpbXM7XG4gICAgICBzd2l0Y2ggKGFyZzAubG9jYXRpb24pIHtcbiAgICAgICAgY2FzZSAnY3B1LXBpbm5lZCc6IHtcbiAgICAgICAgICBjb25zdCBleHBlY3RlZFR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IE5VTUVSSUNfVEVOU09SX1RZUEVfVE9fVFlQRURBUlJBWV9NQVAuZ2V0KHR5cGUpO1xuICAgICAgICAgIGlmICghZXhwZWN0ZWRUeXBlZEFycmF5Q29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGUgXCIke3R5cGV9XCIgdG8gY3JlYXRlIHRlbnNvciBmcm9tIHBpbm5lZCBidWZmZXJgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCEoYXJnMC5kYXRhIGluc3RhbmNlb2YgZXhwZWN0ZWRUeXBlZEFycmF5Q29uc3RydWN0b3IpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBidWZmZXIgc2hvdWxkIGJlIG9mIHR5cGUgJHtleHBlY3RlZFR5cGVkQXJyYXlDb25zdHJ1Y3Rvci5uYW1lfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmNwdURhdGEgPSBhcmcwLmRhdGE7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAndGV4dHVyZSc6IHtcbiAgICAgICAgICBpZiAodHlwZSAhPT0gJ2Zsb2F0MzInKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGB1bnN1cHBvcnRlZCB0eXBlIFwiJHt0eXBlfVwiIHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbSB0ZXh0dXJlYCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuZ3B1VGV4dHVyZURhdGEgPSBhcmcwLnRleHR1cmU7XG4gICAgICAgICAgdGhpcy5kb3dubG9hZGVyID0gYXJnMC5kb3dubG9hZDtcbiAgICAgICAgICB0aGlzLmRpc3Bvc2VyID0gYXJnMC5kaXNwb3NlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ2dwdS1idWZmZXInOiB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgdHlwZSAhPT0gJ2Zsb2F0MzInICYmXG4gICAgICAgICAgICB0eXBlICE9PSAnZmxvYXQxNicgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICdpbnQzMicgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICdpbnQ2NCcgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICd1aW50MzInICYmXG4gICAgICAgICAgICB0eXBlICE9PSAndWludDgnICYmXG4gICAgICAgICAgICB0eXBlICE9PSAnYm9vbCcgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICd1aW50NCcgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICdpbnQ0J1xuICAgICAgICAgICkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgdW5zdXBwb3J0ZWQgdHlwZSBcIiR7dHlwZX1cIiB0byBjcmVhdGUgdGVuc29yIGZyb20gZ3B1IGJ1ZmZlcmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmdwdUJ1ZmZlckRhdGEgPSBhcmcwLmdwdUJ1ZmZlcjtcbiAgICAgICAgICB0aGlzLmRvd25sb2FkZXIgPSBhcmcwLmRvd25sb2FkO1xuICAgICAgICAgIHRoaXMuZGlzcG9zZXIgPSBhcmcwLmRpc3Bvc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAnbWwtdGVuc29yJzoge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHR5cGUgIT09ICdmbG9hdDMyJyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ2Zsb2F0MTYnICYmXG4gICAgICAgICAgICB0eXBlICE9PSAnaW50MzInICYmXG4gICAgICAgICAgICB0eXBlICE9PSAnaW50NjQnICYmXG4gICAgICAgICAgICB0eXBlICE9PSAndWludDMyJyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ3VpbnQ2NCcgJiZcbiAgICAgICAgICAgIHR5cGUgIT09ICdpbnQ4JyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ3VpbnQ4JyAmJlxuICAgICAgICAgICAgdHlwZSAhPT0gJ2Jvb2wnICYmXG4gICAgICAgICAgICB0eXBlICE9PSAndWludDQnICYmXG4gICAgICAgICAgICB0eXBlICE9PSAnaW50NCdcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGUgXCIke3R5cGV9XCIgdG8gY3JlYXRlIHRlbnNvciBmcm9tIE1MVGVuc29yYCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMubWxUZW5zb3JEYXRhID0gYXJnMC5tbFRlbnNvcjtcbiAgICAgICAgICB0aGlzLmRvd25sb2FkZXIgPSBhcmcwLmRvd25sb2FkO1xuICAgICAgICAgIHRoaXMuZGlzcG9zZXIgPSBhcmcwLmRpc3Bvc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRlbnNvciBjb25zdHJ1Y3RvcjogdW5zdXBwb3J0ZWQgbG9jYXRpb24gJyR7dGhpcy5kYXRhTG9jYXRpb259J2ApO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvL1xuICAgICAgLy8gY29uc3RydWN0aW5nIHRlbnNvciBvZiBsb2NhdGlvbiAnY3B1J1xuICAgICAgLy9cbiAgICAgIGxldCBkYXRhOiBUZW5zb3JEYXRhVHlwZTtcbiAgICAgIGxldCBtYXliZURpbXM6IHR5cGVvZiBhcmcxIHwgdHlwZW9mIGFyZzI7XG4gICAgICAvLyBjaGVjayB3aGV0aGVyIGFyZzAgaXMgdHlwZSBvciBkYXRhXG4gICAgICBpZiAodHlwZW9mIGFyZzAgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIC8vXG4gICAgICAgIC8vIE92ZXJyaWRlOiBjb25zdHJ1Y3Rvcih0eXBlLCBkYXRhLCAuLi4pXG4gICAgICAgIC8vXG4gICAgICAgIHR5cGUgPSBhcmcwO1xuICAgICAgICBtYXliZURpbXMgPSBhcmcyO1xuICAgICAgICBpZiAoYXJnMCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAvLyBzdHJpbmcgdGVuc29yXG4gICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGFyZzEpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQSBzdHJpbmcgdGVuc29yJ3MgZGF0YSBtdXN0IGJlIGEgc3RyaW5nIGFycmF5LlwiKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gd2UgZG9uJ3QgY2hlY2sgd2hldGhlciBldmVyeSBlbGVtZW50IGluIHRoZSBhcnJheSBpcyBzdHJpbmc7IHRoaXMgaXMgdG9vIHNsb3cuIHdlIGFzc3VtZSBpdCdzIGNvcnJlY3QgYW5kXG4gICAgICAgICAgLy8gZXJyb3Igd2lsbCBiZSBwb3B1bGF0ZWQgYXQgaW5mZXJlbmNlXG4gICAgICAgICAgZGF0YSA9IGFyZzE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gbnVtZXJpYyB0ZW5zb3JcbiAgICAgICAgICBjb25zdCB0eXBlZEFycmF5Q29uc3RydWN0b3IgPSBOVU1FUklDX1RFTlNPUl9UWVBFX1RPX1RZUEVEQVJSQVlfTUFQLmdldChhcmcwKTtcbiAgICAgICAgICBpZiAodHlwZWRBcnJheUNvbnN0cnVjdG9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYFVuc3VwcG9ydGVkIHRlbnNvciB0eXBlOiAke2FyZzB9LmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShhcmcxKSkge1xuICAgICAgICAgICAgaWYgKChhcmcwID09PSAnZmxvYXQxNicgJiYgdHlwZWRBcnJheUNvbnN0cnVjdG9yID09PSBVaW50MTZBcnJheSkgfHwgYXJnMCA9PT0gJ3VpbnQ0JyB8fCBhcmcwID09PSAnaW50NCcpIHtcbiAgICAgICAgICAgICAgLy8gLSAnZmxvYXQxNic6XG4gICAgICAgICAgICAgIC8vICAgV2hlbiBubyBGbG9hdDE2QXJyYXkgcG9seWZpbGwgaXMgdXNlZCwgd2UgY2Fubm90IGNyZWF0ZSAnZmxvYXQxNicgdGVuc29yIGZyb20gbnVtYmVyIGFycmF5LlxuICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAvLyAgIFRocm93IGVycm9yIGhlcmUgYmVjYXVzZSB3aGVuIHVzZXIgdHJ5IHRvIHVzZSBudW1iZXIgYXJyYXkgYXMgZGF0YSxcbiAgICAgICAgICAgICAgLy8gICBlLmcuIG5ldyBUZW5zb3IoJ2Zsb2F0MTYnLCBbMSwgMiwgMywgNF0sIGRpbXMpKSwgaXQgd2lsbCBhY3R1YWxseSBjYWxsXG4gICAgICAgICAgICAgIC8vICAgVWludDE2QXJyYXkuZnJvbShhcmcxKSB3aGljaCBnZW5lcmF0ZXMgd3JvbmcgZGF0YS5cbiAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgLy8gLSAndWludDQnIGFuZCAnaW50NCc6XG4gICAgICAgICAgICAgIC8vICAgVWludDhBcnJheS5mcm9tKGFyZzEpIHdpbGwgZ2VuZXJhdGUgd3JvbmcgZGF0YSBmb3IgJ3VpbnQ0JyBhbmQgJ2ludDQnIHRlbnNvci5cbiAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgICAgICAgICBgQ3JlYXRpbmcgYSAke2FyZzB9IHRlbnNvciBmcm9tIG51bWJlciBhcnJheSBpcyBub3Qgc3VwcG9ydGVkLiBQbGVhc2UgdXNlICR7dHlwZWRBcnJheUNvbnN0cnVjdG9yLm5hbWV9IGFzIGRhdGEuYCxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYXJnMCA9PT0gJ3VpbnQ2NCcgfHwgYXJnMCA9PT0gJ2ludDY0Jykge1xuICAgICAgICAgICAgICAvLyB1c2UgJ2FzIGFueScgaGVyZSBiZWNhdXNlOlxuICAgICAgICAgICAgICAvLyAxLiBUeXBlU2NyaXB0J3MgY2hlY2sgb24gdHlwZSBvZiAnQXJyYXkuaXNBcnJheSgpJyBkb2VzIG5vdCB3b3JrIHdpdGggcmVhZG9ubHkgYXJyYXlzLlxuICAgICAgICAgICAgICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL21pY3Jvc29mdC9UeXBlU2NyaXB0L2lzc3Vlcy8xNzAwMlxuICAgICAgICAgICAgICAvLyAyLiBUeXBlU2NyaXB0J3MgY2hlY2sgb24gdW5pb24gdHlwZSBvZiAnKEJpZ0ludDY0QXJyYXlDb25zdHJ1Y3RvcnxCaWdVaW50NjRBcnJheUNvbnN0cnVjdG9yKS5mcm9tKCknXG4gICAgICAgICAgICAgIC8vIGRvZXMgbm90IGFjY2VwdCBwYXJhbWV0ZXIgbWFwRm4uXG4gICAgICAgICAgICAgIC8vIDMuIHBhcmFtZXRlcnMgb2YgJ1N1cHBvcnRlZFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnMuZnJvbSgpJyBkb2VzIG5vdCBtYXRjaCB0aGUgcmVxdWlyZW1lbnQgb2YgdGhlIHVuaW9uXG4gICAgICAgICAgICAgIC8vIHR5cGUuXG5cbiAgICAgICAgICAgICAgLy8gYXNzdW1lICdhcmcxJyBpcyBvZiB0eXBlIFwicmVhZG9ubHkgbnVtYmVyW118cmVhZG9ubHkgYmlnaW50W11cIiBoZXJlLlxuXG4gICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgICAgICAgIGRhdGEgPSAodHlwZWRBcnJheUNvbnN0cnVjdG9yIGFzIGFueSkuZnJvbShhcmcxLCBCaWdJbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gYXNzdW1lICdhcmcxJyBpcyBvZiB0eXBlIFwicmVhZG9ubHkgbnVtYmVyW11cIiBoZXJlLlxuICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAgICAgICBkYXRhID0gKHR5cGVkQXJyYXlDb25zdHJ1Y3RvciBhcyBhbnkpLmZyb20oYXJnMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmIChhcmcxIGluc3RhbmNlb2YgdHlwZWRBcnJheUNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICBkYXRhID0gYXJnMTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGFyZzEgaW5zdGFuY2VvZiBVaW50OENsYW1wZWRBcnJheSkge1xuICAgICAgICAgICAgaWYgKGFyZzAgPT09ICd1aW50OCcpIHtcbiAgICAgICAgICAgICAgZGF0YSA9IFVpbnQ4QXJyYXkuZnJvbShhcmcxKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYEEgVWludDhDbGFtcGVkQXJyYXkgdGVuc29yJ3MgZGF0YSBtdXN0IGJlIHR5cGUgb2YgdWludDhgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKGFyZzAgPT09ICdmbG9hdDE2JyAmJiBhcmcxIGluc3RhbmNlb2YgVWludDE2QXJyYXkgJiYgdHlwZWRBcnJheUNvbnN0cnVjdG9yICE9PSBVaW50MTZBcnJheSkge1xuICAgICAgICAgICAgLy8gd2hlbiBGbG9hdDE2QXJyYXkgaXMgYXZhaWxhYmxlIGFuZCBkYXRhIGlzIG9mIHR5cGUgVWludDE2QXJyYXkuXG4gICAgICAgICAgICAvLyBXZSBhbGxvdyBVaW50MTZBcnJheSB0byBiZSBwYXNzZWQgaW4gYXMgZGF0YSBmb3IgJ2Zsb2F0MTYnIHRlbnNvciB1bnRpbCBGbG9hdDE2QXJyYXkgaXMgZ2VuZXJhbGx5XG4gICAgICAgICAgICAvLyBzdXBwb3J0ZWQgaW4gSmF2YVNjcmlwdCBlbnZpcm9ubWVudC5cblxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgICAgIGRhdGEgPSBuZXcgKGdsb2JhbFRoaXMgYXMgYW55KS5GbG9hdDE2QXJyYXkoYXJnMS5idWZmZXIsIGFyZzEuYnl0ZU9mZnNldCwgYXJnMS5sZW5ndGgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBBICR7dHlwZX0gdGVuc29yJ3MgZGF0YSBtdXN0IGJlIHR5cGUgb2YgJHt0eXBlZEFycmF5Q29uc3RydWN0b3J9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvL1xuICAgICAgICAvLyBPdmVycmlkZTogY29uc3RydWN0b3IoZGF0YSwgLi4uKVxuICAgICAgICAvL1xuICAgICAgICBtYXliZURpbXMgPSBhcmcxO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShhcmcwKSkge1xuICAgICAgICAgIC8vIG9ubHkgYm9vbGVhbltdIGFuZCBzdHJpbmdbXSBpcyBzdXBwb3J0ZWRcbiAgICAgICAgICBpZiAoYXJnMC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1RlbnNvciB0eXBlIGNhbm5vdCBiZSBpbmZlcnJlZCBmcm9tIGFuIGVtcHR5IGFycmF5LicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBmaXJzdEVsZW1lbnRUeXBlID0gdHlwZW9mIGFyZzBbMF07XG4gICAgICAgICAgaWYgKGZpcnN0RWxlbWVudFR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0eXBlID0gJ3N0cmluZyc7XG4gICAgICAgICAgICBkYXRhID0gYXJnMDtcbiAgICAgICAgICB9IGVsc2UgaWYgKGZpcnN0RWxlbWVudFR5cGUgPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgdHlwZSA9ICdib29sJztcbiAgICAgICAgICAgIC8vICdhcmcwJyBpcyBvZiB0eXBlICdib29sZWFuW10nLiBVaW50OEFycmF5LmZyb20oYm9vbGVhbltdKSBhY3R1YWxseSB3b3JrcywgYnV0IHR5cGVzY3JpcHQgdGhpbmtzIHRoaXMgaXNcbiAgICAgICAgICAgIC8vIHdyb25nIHR5cGUuIFdlIHVzZSAnYXMgYW55JyB0byBtYWtlIGl0IGhhcHB5LlxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgICAgIGRhdGEgPSBVaW50OEFycmF5LmZyb20oYXJnMCBhcyBhbnlbXSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYEludmFsaWQgZWxlbWVudCB0eXBlIG9mIGRhdGEgYXJyYXk6ICR7Zmlyc3RFbGVtZW50VHlwZX0uYCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGFyZzAgaW5zdGFuY2VvZiBVaW50OENsYW1wZWRBcnJheSkge1xuICAgICAgICAgIHR5cGUgPSAndWludDgnO1xuICAgICAgICAgIGRhdGEgPSBVaW50OEFycmF5LmZyb20oYXJnMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gZ2V0IHRlbnNvciB0eXBlIGZyb20gVHlwZWRBcnJheVxuICAgICAgICAgIGNvbnN0IG1hcHBlZFR5cGUgPSBOVU1FUklDX1RFTlNPUl9UWVBFREFSUkFZX1RPX1RZUEVfTUFQLmdldChcbiAgICAgICAgICAgIGFyZzAuY29uc3RydWN0b3IgYXMgU3VwcG9ydGVkVHlwZWRBcnJheUNvbnN0cnVjdG9ycyxcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChtYXBwZWRUeXBlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYFVuc3VwcG9ydGVkIHR5cGUgZm9yIHRlbnNvciBkYXRhOiAke2FyZzAuY29uc3RydWN0b3J9LmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0eXBlID0gbWFwcGVkVHlwZTtcbiAgICAgICAgICBkYXRhID0gYXJnMCBhcyBTdXBwb3J0ZWRUeXBlZEFycmF5O1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIHR5cGUgYW5kIGRhdGEgaXMgcHJvY2Vzc2VkLCBub3cgcHJvY2Vzc2luZyBkaW1zXG4gICAgICBpZiAobWF5YmVEaW1zID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gYXNzdW1lIDEtRCB0ZW5zb3IgaWYgZGltcyBvbWl0dGVkXG4gICAgICAgIG1heWJlRGltcyA9IFtkYXRhLmxlbmd0aF07XG4gICAgICB9IGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KG1heWJlRGltcykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkEgdGVuc29yJ3MgZGltcyBtdXN0IGJlIGEgbnVtYmVyIGFycmF5XCIpO1xuICAgICAgfVxuICAgICAgZGltcyA9IG1heWJlRGltcyBhcyByZWFkb25seSBudW1iZXJbXTtcblxuICAgICAgdGhpcy5jcHVEYXRhID0gZGF0YTtcbiAgICAgIHRoaXMuZGF0YUxvY2F0aW9uID0gJ2NwdSc7XG4gICAgfVxuXG4gICAgLy8gcGVyZm9ybSBjaGVjayBvbiBkaW1zXG4gICAgY29uc3Qgc2l6ZSA9IGNhbGN1bGF0ZVNpemUoZGltcyk7XG4gICAgLy8gaWYgZGF0YSBpcyBvbiBDUFUsIGNoZWNrIHdoZXRoZXIgZGF0YSBsZW5ndGggbWF0Y2hlcyB0ZW5zb3Igc2l6ZVxuICAgIGlmICh0aGlzLmNwdURhdGEgJiYgc2l6ZSAhPT0gdGhpcy5jcHVEYXRhLmxlbmd0aCkge1xuICAgICAgaWYgKCh0eXBlID09PSAndWludDQnIHx8IHR5cGUgPT09ICdpbnQ0JykgJiYgTWF0aC5jZWlsKHNpemUgLyAyKSA9PT0gdGhpcy5jcHVEYXRhLmxlbmd0aCkge1xuICAgICAgICAvLyBmb3IgKHUpaW50NCwgdGhlIGRhdGEgbGVuZ3RoIGlzIGhhbGYgb2YgdGhlIHRlbnNvciBzaXplLiBTbyB3ZSBjaGVjayB0aGlzIHNwZWNpYWwgY2FzZSB3aGVuIHNpemUgaXMgb2RkLlxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZW5zb3IncyBzaXplKCR7c2l6ZX0pIGRvZXMgbm90IG1hdGNoIGRhdGEgbGVuZ3RoKCR7dGhpcy5jcHVEYXRhLmxlbmd0aH0pLmApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5kaW1zID0gZGltcztcbiAgICB0aGlzLnNpemUgPSBzaXplO1xuICB9XG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIGZhY3RvcnlcbiAgc3RhdGljIGFzeW5jIGZyb21JbWFnZShcbiAgICBpbWFnZTogSW1hZ2VEYXRhIHwgSFRNTEltYWdlRWxlbWVudCB8IEltYWdlQml0bWFwIHwgc3RyaW5nLFxuICAgIG9wdGlvbnM/OlxuICAgICAgfCBUZW5zb3JGcm9tSW1hZ2VEYXRhT3B0aW9uc1xuICAgICAgfCBUZW5zb3JGcm9tSW1hZ2VFbGVtZW50T3B0aW9uc1xuICAgICAgfCBUZW5zb3JGcm9tSW1hZ2VCaXRtYXBPcHRpb25zXG4gICAgICB8IFRlbnNvckZyb21VcmxPcHRpb25zLFxuICApOiBQcm9taXNlPFRlbnNvckludGVyZmFjZT4ge1xuICAgIHJldHVybiB0ZW5zb3JGcm9tSW1hZ2UoaW1hZ2UsIG9wdGlvbnMpO1xuICB9XG5cbiAgc3RhdGljIGZyb21UZXh0dXJlPFQgZXh0ZW5kcyBUZW5zb3JJbnRlcmZhY2UuVGV4dHVyZURhdGFUeXBlcz4oXG4gICAgdGV4dHVyZTogVGVuc29yVGV4dHVyZVR5cGUsXG4gICAgb3B0aW9uczogVGVuc29yRnJvbVRleHR1cmVPcHRpb25zPFQ+LFxuICApOiBUZW5zb3JJbnRlcmZhY2Uge1xuICAgIHJldHVybiB0ZW5zb3JGcm9tVGV4dHVyZSh0ZXh0dXJlLCBvcHRpb25zKTtcbiAgfVxuXG4gIHN0YXRpYyBmcm9tR3B1QnVmZmVyPFQgZXh0ZW5kcyBUZW5zb3JJbnRlcmZhY2UuR3B1QnVmZmVyRGF0YVR5cGVzPihcbiAgICBncHVCdWZmZXI6IFRlbnNvckdwdUJ1ZmZlclR5cGUsXG4gICAgb3B0aW9uczogVGVuc29yRnJvbUdwdUJ1ZmZlck9wdGlvbnM8VD4sXG4gICk6IFRlbnNvckludGVyZmFjZSB7XG4gICAgcmV0dXJuIHRlbnNvckZyb21HcHVCdWZmZXIoZ3B1QnVmZmVyLCBvcHRpb25zKTtcbiAgfVxuXG4gIHN0YXRpYyBmcm9tTUxUZW5zb3I8VCBleHRlbmRzIFRlbnNvckludGVyZmFjZS5NTFRlbnNvckRhdGFUeXBlcz4oXG4gICAgbWxUZW5zb3I6IFRlbnNvck1MVGVuc29yVHlwZSxcbiAgICBvcHRpb25zOiBUZW5zb3JGcm9tTUxUZW5zb3JPcHRpb25zPFQ+LFxuICApOiBUZW5zb3JJbnRlcmZhY2Uge1xuICAgIHJldHVybiB0ZW5zb3JGcm9tTUxUZW5zb3IobWxUZW5zb3IsIG9wdGlvbnMpO1xuICB9XG5cbiAgc3RhdGljIGZyb21QaW5uZWRCdWZmZXI8VCBleHRlbmRzIFRlbnNvckludGVyZmFjZS5DcHVQaW5uZWREYXRhVHlwZXM+KFxuICAgIHR5cGU6IFQsXG4gICAgYnVmZmVyOiBUZW5zb3JJbnRlcmZhY2UuRGF0YVR5cGVNYXBbVF0sXG4gICAgZGltcz86IHJlYWRvbmx5IG51bWJlcltdLFxuICApOiBUZW5zb3Ige1xuICAgIHJldHVybiB0ZW5zb3JGcm9tUGlubmVkQnVmZmVyKHR5cGUsIGJ1ZmZlciwgZGltcyk7XG4gIH1cblxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBjb252ZXJzaW9uc1xuICB0b0RhdGFVUkwob3B0aW9ucz86IFRlbnNvclRvRGF0YVVybE9wdGlvbnMpOiBzdHJpbmcge1xuICAgIHJldHVybiB0ZW5zb3JUb0RhdGFVUkwodGhpcywgb3B0aW9ucyk7XG4gIH1cblxuICB0b0ltYWdlRGF0YShvcHRpb25zPzogVGVuc29yVG9JbWFnZURhdGFPcHRpb25zKTogSW1hZ2VEYXRhIHtcbiAgICByZXR1cm4gdGVuc29yVG9JbWFnZURhdGEodGhpcywgb3B0aW9ucyk7XG4gIH1cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gcHVibGljIGZpZWxkc1xuICByZWFkb25seSBkaW1zOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgdHlwZTogVGVuc29yVHlwZTtcbiAgcmVhZG9ubHkgc2l6ZTogbnVtYmVyO1xuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBwcml2YXRlIGZpZWxkc1xuXG4gIC8qKlxuICAgKiBzdG9yZXMgdGhlIGxvY2F0aW9uIG9mIHRoZSBkYXRhLlxuICAgKi9cbiAgcHJpdmF0ZSBkYXRhTG9jYXRpb246IFRlbnNvckRhdGFMb2NhdGlvbjtcblxuICAvKipcbiAgICogc3RvcmVzIHRoZSBkYXRhIG9uIENQVSwgaWYgbG9jYXRpb24gaXMgJ2NwdScgb3IgJ2NwdS1waW5uZWQnLiBvdGhlcndpc2UgZW1wdHkuXG4gICAqL1xuICBwcml2YXRlIGNwdURhdGE/OiBUZW5zb3JEYXRhVHlwZTtcblxuICAvKipcbiAgICogc3RvcmVzIHRoZSB1bmRlcmx5aW5nIHRleHR1cmUgd2hlbiBsb2NhdGlvbiBpcyAndGV4dHVyZScuIG90aGVyd2lzZSBlbXB0eS5cbiAgICovXG4gIHByaXZhdGUgZ3B1VGV4dHVyZURhdGE/OiBUZW5zb3JUZXh0dXJlVHlwZTtcblxuICAvKipcbiAgICogc3RvcmVzIHRoZSB1bmRlcmx5aW5nIEdQVSBidWZmZXIgd2hlbiBsb2NhdGlvbiBpcyAnZ3B1LWJ1ZmZlcicuIG90aGVyd2lzZSBlbXB0eS5cbiAgICovXG4gIHByaXZhdGUgZ3B1QnVmZmVyRGF0YT86IFRlbnNvckdwdUJ1ZmZlclR5cGU7XG5cbiAgLyoqXG4gICAqIHN0b3JlcyB0aGUgdW5kZXJseWluZyBXZWJOTiBNTFRlbnNvciB3aGVuIGxvY2F0aW9uIGlzICdtbC10ZW5zb3InLiBvdGhlcndpc2UgZW1wdHkuXG4gICAqL1xuICBwcml2YXRlIG1sVGVuc29yRGF0YT86IFRlbnNvck1MVGVuc29yVHlwZTtcblxuICAvKipcbiAgICogc3RvcmVzIGFuIG9wdGlvbmFsIGRvd25sb2FkZXIgZnVuY3Rpb24gdG8gZG93bmxvYWQgZGF0YSBmcm9tIEdQVSB0byBDUFUuXG4gICAqL1xuICBwcml2YXRlIGRvd25sb2FkZXI/KCk6IFByb21pc2U8VGVuc29yRGF0YVR5cGU+O1xuXG4gIC8qKlxuICAgKiBhIGZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSBkYXRhIGlzIGJlaW5nIGRvd25sb2FkZWQgZnJvbSBHUFUgdG8gQ1BVLlxuICAgKi9cbiAgcHJpdmF0ZSBpc0Rvd25sb2FkaW5nPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogc3RvcmVzIGFuIG9wdGlvbmFsIGRpc3Bvc2VyIGZ1bmN0aW9uIHRvIGRpc3Bvc2UgdGhlIHVuZGVybHlpbmcgZGF0YS5cbiAgICovXG4gIHByaXZhdGUgZGlzcG9zZXI/KCk6IHZvaWQ7XG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIHByb3BlcnRpZXNcbiAgZ2V0IGRhdGEoKTogVGVuc29yRGF0YVR5cGUge1xuICAgIHRoaXMuZW5zdXJlVmFsaWQoKTtcbiAgICBpZiAoIXRoaXMuY3B1RGF0YSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnVGhlIGRhdGEgaXMgbm90IG9uIENQVS4gVXNlIGBnZXREYXRhKClgIHRvIGRvd25sb2FkIEdQVSBkYXRhIHRvIENQVSwgJyArXG4gICAgICAgICAgJ29yIHVzZSBgdGV4dHVyZWAgb3IgYGdwdUJ1ZmZlcmAgcHJvcGVydHkgdG8gYWNjZXNzIHRoZSBHUFUgZGF0YSBkaXJlY3RseS4nLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY3B1RGF0YTtcbiAgfVxuXG4gIGdldCBsb2NhdGlvbigpOiBUZW5zb3JEYXRhTG9jYXRpb24ge1xuICAgIHJldHVybiB0aGlzLmRhdGFMb2NhdGlvbjtcbiAgfVxuXG4gIGdldCB0ZXh0dXJlKCk6IFRlbnNvclRleHR1cmVUeXBlIHtcbiAgICB0aGlzLmVuc3VyZVZhbGlkKCk7XG4gICAgaWYgKCF0aGlzLmdwdVRleHR1cmVEYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBkYXRhIGlzIG5vdCBzdG9yZWQgYXMgYSBXZWJHTCB0ZXh0dXJlLicpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5ncHVUZXh0dXJlRGF0YTtcbiAgfVxuXG4gIGdldCBncHVCdWZmZXIoKTogVGVuc29yR3B1QnVmZmVyVHlwZSB7XG4gICAgdGhpcy5lbnN1cmVWYWxpZCgpO1xuICAgIGlmICghdGhpcy5ncHVCdWZmZXJEYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBkYXRhIGlzIG5vdCBzdG9yZWQgYXMgYSBXZWJHUFUgYnVmZmVyLicpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5ncHVCdWZmZXJEYXRhO1xuICB9XG5cbiAgZ2V0IG1sVGVuc29yKCk6IFRlbnNvck1MVGVuc29yVHlwZSB7XG4gICAgdGhpcy5lbnN1cmVWYWxpZCgpO1xuICAgIGlmICghdGhpcy5tbFRlbnNvckRhdGEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGRhdGEgaXMgbm90IHN0b3JlZCBhcyBhIFdlYk5OIE1MVGVuc29yLicpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5tbFRlbnNvckRhdGE7XG4gIH1cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gbWV0aG9kc1xuXG4gIGFzeW5jIGdldERhdGEocmVsZWFzZURhdGE/OiBib29sZWFuKTogUHJvbWlzZTxUZW5zb3JEYXRhVHlwZT4ge1xuICAgIHRoaXMuZW5zdXJlVmFsaWQoKTtcbiAgICBzd2l0Y2ggKHRoaXMuZGF0YUxvY2F0aW9uKSB7XG4gICAgICBjYXNlICdjcHUnOlxuICAgICAgY2FzZSAnY3B1LXBpbm5lZCc6XG4gICAgICAgIHJldHVybiB0aGlzLmRhdGE7XG4gICAgICBjYXNlICd0ZXh0dXJlJzpcbiAgICAgIGNhc2UgJ2dwdS1idWZmZXInOlxuICAgICAgY2FzZSAnbWwtdGVuc29yJzoge1xuICAgICAgICBpZiAoIXRoaXMuZG93bmxvYWRlcikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGN1cnJlbnQgdGVuc29yIGlzIG5vdCBjcmVhdGVkIHdpdGggYSBzcGVjaWZpZWQgZGF0YSBkb3dubG9hZGVyLicpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzRG93bmxvYWRpbmcpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBjdXJyZW50IHRlbnNvciBpcyBiZWluZyBkb3dubG9hZGVkLicpO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdGhpcy5pc0Rvd25sb2FkaW5nID0gdHJ1ZTtcbiAgICAgICAgICBjb25zdCBkYXRhID0gYXdhaXQgdGhpcy5kb3dubG9hZGVyKCk7XG4gICAgICAgICAgdGhpcy5kb3dubG9hZGVyID0gdW5kZWZpbmVkO1xuICAgICAgICAgIHRoaXMuZGF0YUxvY2F0aW9uID0gJ2NwdSc7XG4gICAgICAgICAgdGhpcy5jcHVEYXRhID0gZGF0YTtcblxuICAgICAgICAgIGlmIChyZWxlYXNlRGF0YSAmJiB0aGlzLmRpc3Bvc2VyKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3Bvc2VyKCk7XG4gICAgICAgICAgICB0aGlzLmRpc3Bvc2VyID0gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIHRoaXMuaXNEb3dubG9hZGluZyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCBnZXQgZGF0YSBmcm9tIGxvY2F0aW9uOiAke3RoaXMuZGF0YUxvY2F0aW9ufWApO1xuICAgIH1cbiAgfVxuXG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaXNEb3dubG9hZGluZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgY3VycmVudCB0ZW5zb3IgaXMgYmVpbmcgZG93bmxvYWRlZC4nKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5kaXNwb3Nlcikge1xuICAgICAgdGhpcy5kaXNwb3NlcigpO1xuICAgICAgdGhpcy5kaXNwb3NlciA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdGhpcy5jcHVEYXRhID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuZ3B1VGV4dHVyZURhdGEgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5ncHVCdWZmZXJEYXRhID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubWxUZW5zb3JEYXRhID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuZG93bmxvYWRlciA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmlzRG93bmxvYWRpbmcgPSB1bmRlZmluZWQ7XG5cbiAgICB0aGlzLmRhdGFMb2NhdGlvbiA9ICdub25lJztcbiAgfVxuXG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIHRlbnNvciB1dGlsaXRpZXNcbiAgcHJpdmF0ZSBlbnN1cmVWYWxpZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kYXRhTG9jYXRpb24gPT09ICdub25lJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgdGVuc29yIGlzIGRpc3Bvc2VkLicpO1xuICAgIH1cbiAgfVxuXG4gIHJlc2hhcGUoZGltczogcmVhZG9ubHkgbnVtYmVyW10pOiBUZW5zb3JJbnRlcmZhY2Uge1xuICAgIHRoaXMuZW5zdXJlVmFsaWQoKTtcbiAgICBpZiAodGhpcy5kb3dubG9hZGVyIHx8IHRoaXMuZGlzcG9zZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHJlc2hhcGUgYSB0ZW5zb3IgdGhhdCBvd25zIEdQVSByZXNvdXJjZS4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRlbnNvclJlc2hhcGUodGhpcywgZGltcyk7XG4gIH1cbiAgLy8gI2VuZHJlZ2lvblxufVxuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUZW5zb3JGYWN0b3J5IH0gZnJvbSAnLi90ZW5zb3ItZmFjdG9yeS5qcyc7XG5pbXBvcnQgeyBUZW5zb3IgYXMgVGVuc29ySW1wbCB9IGZyb20gJy4vdGVuc29yLWltcGwuanMnO1xuaW1wb3J0IHsgVHlwZWRUZW5zb3JVdGlscyB9IGZyb20gJy4vdGVuc29yLXV0aWxzLmpzJztcbmltcG9ydCB7IFRyeUdldEdsb2JhbFR5cGUgfSBmcm9tICcuL3R5cGUtaGVscGVyLmpzJztcblxuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlZGVjbGFyZSAqL1xuXG4vKipcbiAqIHJlcHJlc2VudCBhIGJhc2ljIHRlbnNvciB3aXRoIHNwZWNpZmllZCBkaW1lbnNpb25zIGFuZCBkYXRhIHR5cGUuXG4gKi9cbmludGVyZmFjZSBUeXBlZFRlbnNvckJhc2U8VCBleHRlbmRzIFRlbnNvci5UeXBlPiB7XG4gIC8qKlxuICAgKiBHZXQgdGhlIGRpbWVuc2lvbnMgb2YgdGhlIHRlbnNvci5cbiAgICovXG4gIHJlYWRvbmx5IGRpbXM6IHJlYWRvbmx5IG51bWJlcltdO1xuICAvKipcbiAgICogR2V0IHRoZSBkYXRhIHR5cGUgb2YgdGhlIHRlbnNvci5cbiAgICovXG4gIHJlYWRvbmx5IHR5cGU6IFQ7XG4gIC8qKlxuICAgKiBHZXQgdGhlIGJ1ZmZlciBkYXRhIG9mIHRoZSB0ZW5zb3IuXG4gICAqXG4gICAqIElmIHRoZSBkYXRhIGlzIG5vdCBvbiBDUFUgKGVnLiBpdCdzIGluIHRoZSBmb3JtIG9mIFdlYkdMIHRleHR1cmUgb3IgV2ViR1BVIGJ1ZmZlciksIHRocm93IGVycm9yLlxuICAgKi9cbiAgcmVhZG9ubHkgZGF0YTogVGVuc29yLkRhdGFUeXBlTWFwW1RdO1xuICAvKipcbiAgICogR2V0IHRoZSBsb2NhdGlvbiBvZiB0aGUgZGF0YS5cbiAgICovXG4gIHJlYWRvbmx5IGxvY2F0aW9uOiBUZW5zb3IuRGF0YUxvY2F0aW9uO1xuICAvKipcbiAgICogR2V0IHRoZSBXZWJHTCB0ZXh0dXJlIHRoYXQgaG9sZHMgdGhlIHRlbnNvciBkYXRhLlxuICAgKlxuICAgKiBJZiB0aGUgZGF0YSBpcyBub3Qgb24gR1BVIGFzIFdlYkdMIHRleHR1cmUsIHRocm93IGVycm9yLlxuICAgKi9cbiAgcmVhZG9ubHkgdGV4dHVyZTogVGVuc29yLlRleHR1cmVUeXBlO1xuICAvKipcbiAgICogR2V0IHRoZSBXZWJHUFUgYnVmZmVyIHRoYXQgaG9sZHMgdGhlIHRlbnNvciBkYXRhLlxuICAgKlxuICAgKiBJZiB0aGUgZGF0YSBpcyBub3Qgb24gR1BVIGFzIFdlYkdQVSBidWZmZXIsIHRocm93IGVycm9yLlxuICAgKi9cbiAgcmVhZG9ubHkgZ3B1QnVmZmVyOiBUZW5zb3IuR3B1QnVmZmVyVHlwZTtcblxuICAvKipcbiAgICogR2V0IHRoZSBXZWJOTiBNTFRlbnNvciB0aGF0IGhvbGRzIHRoZSB0ZW5zb3IgZGF0YS5cbiAgICpcbiAgICogSWYgdGhlIGRhdGEgaXMgbm90IGluIGEgV2ViTk4gTUxUZW5zb3IsIHRocm93IGVycm9yLlxuICAgKi9cbiAgcmVhZG9ubHkgbWxUZW5zb3I6IFRlbnNvci5NTFRlbnNvclR5cGU7XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgYnVmZmVyIGRhdGEgb2YgdGhlIHRlbnNvci5cbiAgICpcbiAgICogSWYgdGhlIGRhdGEgaXMgb24gQ1BVLCByZXR1cm5zIHRoZSBkYXRhIGltbWVkaWF0ZWx5LlxuICAgKiBJZiB0aGUgZGF0YSBpcyBvbiBHUFUsIGRvd25sb2FkcyB0aGUgZGF0YSBhbmQgcmV0dXJucyB0aGUgcHJvbWlzZS5cbiAgICpcbiAgICogQHBhcmFtIHJlbGVhc2VEYXRhIC0gd2hldGhlciByZWxlYXNlIHRoZSBkYXRhIG9uIEdQVS4gSWdub3JlIGlmIGRhdGEgaXMgYWxyZWFkeSBvbiBDUFUuXG4gICAqL1xuICBnZXREYXRhKHJlbGVhc2VEYXRhPzogYm9vbGVhbik6IFByb21pc2U8VGVuc29yLkRhdGFUeXBlTWFwW1RdPjtcblxuICAvKipcbiAgICogRGlzcG9zZSB0aGUgdGVuc29yIGRhdGEuXG4gICAqXG4gICAqIElmIHRoZSBkYXRhIGlzIG9uIENQVSwgcmVtb3ZlIGl0cyBpbnRlcm5hbCByZWZlcmVuY2UgdG8gdGhlIHVuZGVybHlpbmcgZGF0YS5cbiAgICogSWYgdGhlIGRhdGEgaXMgb24gR1BVLCByZWxlYXNlIHRoZSBkYXRhIG9uIEdQVS5cbiAgICpcbiAgICogQWZ0ZXIgY2FsbGluZyB0aGlzIGZ1bmN0aW9uLCB0aGUgdGVuc29yIGlzIGNvbnNpZGVyZWQgbm8gbG9uZ2VyIHZhbGlkLiBJdHMgbG9jYXRpb24gd2lsbCBiZSBzZXQgdG8gJ25vbmUnLlxuICAgKi9cbiAgZGlzcG9zZSgpOiB2b2lkO1xufVxuXG5leHBvcnQgZGVjbGFyZSBuYW1lc3BhY2UgVGVuc29yIHtcbiAgaW50ZXJmYWNlIERhdGFUeXBlTWFwIHtcbiAgICBmbG9hdDMyOiBGbG9hdDMyQXJyYXk7XG4gICAgdWludDg6IFVpbnQ4QXJyYXk7XG4gICAgaW50ODogSW50OEFycmF5O1xuICAgIHVpbnQxNjogVWludDE2QXJyYXk7XG4gICAgaW50MTY6IEludDE2QXJyYXk7XG4gICAgaW50MzI6IEludDMyQXJyYXk7XG4gICAgaW50NjQ6IEJpZ0ludDY0QXJyYXk7XG4gICAgc3RyaW5nOiBzdHJpbmdbXTtcbiAgICBib29sOiBVaW50OEFycmF5O1xuICAgIGZsb2F0MTY6IFVpbnQxNkFycmF5OyAvLyBLZWVwIHVzaW5nIFVpbnQxNkFycmF5IHVudGlsIHdlIGhhdmUgYSBjb25jcmV0ZSBzb2x1dGlvbiBmb3IgZmxvYXQgMTYuXG4gICAgZmxvYXQ2NDogRmxvYXQ2NEFycmF5O1xuICAgIHVpbnQzMjogVWludDMyQXJyYXk7XG4gICAgdWludDY0OiBCaWdVaW50NjRBcnJheTtcbiAgICAvLyBjb21wbGV4NjQ6IG5ldmVyO1xuICAgIC8vIGNvbXBsZXgxMjg6IG5ldmVyO1xuICAgIC8vIGJmbG9hdDE2OiBuZXZlcjtcbiAgICB1aW50NDogVWludDhBcnJheTtcbiAgICBpbnQ0OiBJbnQ4QXJyYXk7XG4gIH1cblxuICBpbnRlcmZhY2UgRWxlbWVudFR5cGVNYXAge1xuICAgIGZsb2F0MzI6IG51bWJlcjtcbiAgICB1aW50ODogbnVtYmVyO1xuICAgIGludDg6IG51bWJlcjtcbiAgICB1aW50MTY6IG51bWJlcjtcbiAgICBpbnQxNjogbnVtYmVyO1xuICAgIGludDMyOiBudW1iZXI7XG4gICAgaW50NjQ6IGJpZ2ludDtcbiAgICBzdHJpbmc6IHN0cmluZztcbiAgICBib29sOiBib29sZWFuO1xuICAgIGZsb2F0MTY6IG51bWJlcjsgLy8gS2VlcCB1c2luZyBVaW50MTZBcnJheSB1bnRpbCB3ZSBoYXZlIGEgY29uY3JldGUgc29sdXRpb24gZm9yIGZsb2F0IDE2LlxuICAgIGZsb2F0NjQ6IG51bWJlcjtcbiAgICB1aW50MzI6IG51bWJlcjtcbiAgICB1aW50NjQ6IGJpZ2ludDtcbiAgICAvLyBjb21wbGV4NjQ6IG5ldmVyO1xuICAgIC8vIGNvbXBsZXgxMjg6IG5ldmVyO1xuICAgIC8vIGJmbG9hdDE2OiBuZXZlcjtcbiAgICB1aW50NDogbnVtYmVyO1xuICAgIGludDQ6IG51bWJlcjtcbiAgfVxuXG4gIHR5cGUgRGF0YVR5cGUgPSBEYXRhVHlwZU1hcFtUeXBlXTtcbiAgdHlwZSBFbGVtZW50VHlwZSA9IEVsZW1lbnRUeXBlTWFwW1R5cGVdO1xuXG4gIC8qKlxuICAgKiBzdXBwb3J0ZWQgZGF0YSB0eXBlcyBmb3IgY29uc3RydWN0aW5nIGEgdGVuc29yIGZyb20gYSBwaW5uZWQgQ1BVIGJ1ZmZlclxuICAgKi9cbiAgZXhwb3J0IHR5cGUgQ3B1UGlubmVkRGF0YVR5cGVzID0gRXhjbHVkZTxUZW5zb3IuVHlwZSwgJ3N0cmluZyc+O1xuXG4gIC8qKlxuICAgKiB0eXBlIGFsaWFzIGZvciBXZWJHTCB0ZXh0dXJlXG4gICAqL1xuICBleHBvcnQgdHlwZSBUZXh0dXJlVHlwZSA9IFdlYkdMVGV4dHVyZTtcblxuICAvKipcbiAgICogc3VwcG9ydGVkIGRhdGEgdHlwZXMgZm9yIGNvbnN0cnVjdGluZyBhIHRlbnNvciBmcm9tIGEgV2ViR0wgdGV4dHVyZVxuICAgKi9cbiAgZXhwb3J0IHR5cGUgVGV4dHVyZURhdGFUeXBlcyA9ICdmbG9hdDMyJztcblxuICB0eXBlIEdwdUJ1ZmZlclR5cGVGYWxsYmFjayA9IHsgc2l6ZTogbnVtYmVyOyBtYXBTdGF0ZTogJ3VubWFwcGVkJyB8ICdwZW5kaW5nJyB8ICdtYXBwZWQnIH07XG4gIC8qKlxuICAgKiB0eXBlIGFsaWFzIGZvciBXZWJHUFUgYnVmZmVyXG4gICAqL1xuICBleHBvcnQgdHlwZSBHcHVCdWZmZXJUeXBlID0gVHJ5R2V0R2xvYmFsVHlwZTwnR1BVQnVmZmVyJywgR3B1QnVmZmVyVHlwZUZhbGxiYWNrPjtcblxuICB0eXBlIE1MVGVuc29yVHlwZUZhbGxiYWNrID0geyBkZXN0cm95KCk6IHZvaWQgfTtcbiAgLyoqXG4gICAqIHR5cGUgYWxpYXMgZm9yIFdlYk5OIE1MVGVuc29yXG4gICAqXG4gICAqIFRoZSBzcGVjaWZpY2F0aW9uIGZvciBXZWJOTidzIE1MVGVuc29yIGlzIGN1cnJlbnRseSBpbiBmbHV4LlxuICAgKi9cbiAgZXhwb3J0IHR5cGUgTUxUZW5zb3JUeXBlID0gVHJ5R2V0R2xvYmFsVHlwZTwnTUxUZW5zb3InLCBNTFRlbnNvclR5cGVGYWxsYmFjaz47XG5cbiAgLyoqXG4gICAqIHN1cHBvcnRlZCBkYXRhIHR5cGVzIGZvciBjb25zdHJ1Y3RpbmcgYSB0ZW5zb3IgZnJvbSBhIFdlYkdQVSBidWZmZXJcbiAgICovXG4gIGV4cG9ydCB0eXBlIEdwdUJ1ZmZlckRhdGFUeXBlcyA9ICdmbG9hdDMyJyB8ICdmbG9hdDE2JyB8ICdpbnQzMicgfCAnaW50NjQnIHwgJ3VpbnQzMicgfCAndWludDgnIHwgJ2Jvb2wnO1xuXG4gIC8qKlxuICAgKiBzdXBwb3J0ZWQgZGF0YSB0eXBlcyBmb3IgY29uc3RydWN0aW5nIGEgdGVuc29yIGZyb20gYSBXZWJOTiBNTFRlbnNvclxuICAgKi9cbiAgZXhwb3J0IHR5cGUgTUxUZW5zb3JEYXRhVHlwZXMgPVxuICAgIHwgJ2Zsb2F0MzInXG4gICAgfCAnZmxvYXQxNidcbiAgICB8ICdpbnQ4J1xuICAgIHwgJ3VpbnQ4J1xuICAgIHwgJ2ludDMyJ1xuICAgIHwgJ3VpbnQzMidcbiAgICB8ICdpbnQ2NCdcbiAgICB8ICd1aW50NjQnXG4gICAgfCAnYm9vbCdcbiAgICB8ICd1aW50NCdcbiAgICB8ICdpbnQ0JztcblxuICAvKipcbiAgICogcmVwcmVzZW50IHdoZXJlIHRoZSB0ZW5zb3IgZGF0YSBpcyBzdG9yZWRcbiAgICovXG4gIGV4cG9ydCB0eXBlIERhdGFMb2NhdGlvbiA9ICdub25lJyB8ICdjcHUnIHwgJ2NwdS1waW5uZWQnIHwgJ3RleHR1cmUnIHwgJ2dwdS1idWZmZXInIHwgJ21sLXRlbnNvcic7XG5cbiAgLyoqXG4gICAqIHJlcHJlc2VudCB0aGUgZGF0YSB0eXBlIG9mIGEgdGVuc29yXG4gICAqL1xuICBleHBvcnQgdHlwZSBUeXBlID0ga2V5b2YgRGF0YVR5cGVNYXA7XG59XG5cbi8qKlxuICogUmVwcmVzZW50IG11bHRpLWRpbWVuc2lvbmFsIGFycmF5cyB0byBmZWVkIHRvIG9yIGZldGNoIGZyb20gbW9kZWwgaW5mZXJlbmNpbmcuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVHlwZWRUZW5zb3I8VCBleHRlbmRzIFRlbnNvci5UeXBlPiBleHRlbmRzIFR5cGVkVGVuc29yQmFzZTxUPiwgVHlwZWRUZW5zb3JVdGlsczxUPiB7fVxuLyoqXG4gKiBSZXByZXNlbnQgbXVsdGktZGltZW5zaW9uYWwgYXJyYXlzIHRvIGZlZWQgdG8gb3IgZmV0Y2ggZnJvbSBtb2RlbCBpbmZlcmVuY2luZy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZW5zb3IgZXh0ZW5kcyBUeXBlZFRlbnNvckJhc2U8VGVuc29yLlR5cGU+LCBUeXBlZFRlbnNvclV0aWxzPFRlbnNvci5UeXBlPiB7fVxuXG4vKipcbiAqIHR5cGUgVGVuc29yQ29uc3RydWN0b3IgZGVmaW5lcyB0aGUgY29uc3RydWN0b3JzIG9mICdUZW5zb3InIHRvIGNyZWF0ZSBDUFUgdGVuc29yIGluc3RhbmNlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JDb25zdHJ1Y3RvciBleHRlbmRzIFRlbnNvckZhY3Rvcnkge1xuICAvLyAjcmVnaW9uIENQVSB0ZW5zb3IgLSBzcGVjaWZ5IGVsZW1lbnQgdHlwZVxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHN0cmluZyB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIHR5cGUsIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSB0eXBlIC0gU3BlY2lmeSB0aGUgZWxlbWVudCB0eXBlLlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKFxuICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgIGRhdGE6IFRlbnNvci5EYXRhVHlwZU1hcFsnc3RyaW5nJ10gfCByZWFkb25seSBzdHJpbmdbXSxcbiAgICBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10sXG4gICk6IFR5cGVkVGVuc29yPCdzdHJpbmcnPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IGJvb2wgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiB0eXBlLCBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gdHlwZSAtIFNwZWNpZnkgdGhlIGVsZW1lbnQgdHlwZS5cbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChcbiAgICB0eXBlOiAnYm9vbCcsXG4gICAgZGF0YTogVGVuc29yLkRhdGFUeXBlTWFwWydib29sJ10gfCByZWFkb25seSBib29sZWFuW10sXG4gICAgZGltcz86IHJlYWRvbmx5IG51bWJlcltdLFxuICApOiBUeXBlZFRlbnNvcjwnYm9vbCc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgdWludDggdGVuc29yIG9iamVjdCBmcm9tIGEgVWludDhDbGFtcGVkQXJyYXksIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSB0eXBlIC0gU3BlY2lmeSB0aGUgZWxlbWVudCB0eXBlLlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKHR5cGU6ICd1aW50OCcsIGRhdGE6IFVpbnQ4Q2xhbXBlZEFycmF5LCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwndWludDgnPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IDY0LWJpdCBpbnRlZ2VyIHR5cGVkIHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gdHlwZSwgZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIHR5cGUgLSBTcGVjaWZ5IHRoZSBlbGVtZW50IHR5cGUuXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyA8VCBleHRlbmRzICd1aW50NjQnIHwgJ2ludDY0Jz4oXG4gICAgdHlwZTogVCxcbiAgICBkYXRhOiBUZW5zb3IuRGF0YVR5cGVNYXBbVF0gfCByZWFkb25seSBiaWdpbnRbXSB8IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSxcbiAgKTogVHlwZWRUZW5zb3I8VD47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyBudW1lcmljIHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gdHlwZSwgZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIHR5cGUgLSBTcGVjaWZ5IHRoZSBlbGVtZW50IHR5cGUuXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyA8VCBleHRlbmRzIEV4Y2x1ZGU8VGVuc29yLlR5cGUsICdzdHJpbmcnIHwgJ2Jvb2wnIHwgJ3VpbnQ2NCcgfCAnaW50NjQnPj4oXG4gICAgdHlwZTogVCxcbiAgICBkYXRhOiBUZW5zb3IuRGF0YVR5cGVNYXBbVF0gfCByZWFkb25seSBudW1iZXJbXSxcbiAgICBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10sXG4gICk6IFR5cGVkVGVuc29yPFQ+O1xuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBDUFUgdGVuc29yIC0gaW5mZXIgZWxlbWVudCB0eXBlc1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgZmxvYXQzMiB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogRmxvYXQzMkFycmF5LCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwnZmxvYXQzMic+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgaW50OCB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogSW50OEFycmF5LCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwnaW50OCc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgdWludDggdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IFVpbnQ4QXJyYXksIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCd1aW50OCc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgdWludDggdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IFVpbnQ4Q2xhbXBlZEFycmF5LCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwndWludDgnPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHVpbnQxNiB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogVWludDE2QXJyYXksIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCd1aW50MTYnPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IGludDE2IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiBJbnQxNkFycmF5LCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwnaW50MTYnPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IGludDMyIHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiBJbnQzMkFycmF5LCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwnaW50MzInPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IGludDY0IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiBCaWdJbnQ2NEFycmF5LCBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10pOiBUeXBlZFRlbnNvcjwnaW50NjQnPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHN0cmluZyB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogcmVhZG9ubHkgc3RyaW5nW10sIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCdzdHJpbmcnPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IGJvb2wgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IHJlYWRvbmx5IGJvb2xlYW5bXSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J2Jvb2wnPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IGZsb2F0NjQgdGVuc29yIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBkYXRhIGFuZCBkaW1zLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKGRhdGE6IEZsb2F0NjRBcnJheSwgZGltcz86IHJlYWRvbmx5IG51bWJlcltdKTogVHlwZWRUZW5zb3I8J2Zsb2F0NjQnPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHVpbnQzMiB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogVWludDMyQXJyYXksIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCd1aW50MzInPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHVpbnQ2NCB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gU3BlY2lmeSB0aGUgQ1BVIHRlbnNvciBkYXRhLlxuICAgKiBAcGFyYW0gZGltcyAtIFNwZWNpZnkgdGhlIGRpbWVuc2lvbiBvZiB0aGUgdGVuc29yLiBJZiBvbWl0dGVkLCBhIDEtRCB0ZW5zb3IgaXMgYXNzdW1lZC5cbiAgICovXG4gIG5ldyAoZGF0YTogQmlnVWludDY0QXJyYXksIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFR5cGVkVGVuc29yPCd1aW50NjQnPjtcblxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBDUFUgdGVuc29yIC0gZmFsbCBiYWNrIHRvIG5vbi1nZW5lcmljIHRlbnNvciB0eXBlIGRlY2xhcmF0aW9uXG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIG5ldyB0ZW5zb3Igb2JqZWN0IGZyb20gdGhlIGdpdmVuIHR5cGUsIGRhdGEgYW5kIGRpbXMuXG4gICAqXG4gICAqIEBwYXJhbSB0eXBlIC0gU3BlY2lmeSB0aGUgZWxlbWVudCB0eXBlLlxuICAgKiBAcGFyYW0gZGF0YSAtIFNwZWNpZnkgdGhlIENQVSB0ZW5zb3IgZGF0YS5cbiAgICogQHBhcmFtIGRpbXMgLSBTcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqL1xuICBuZXcgKFxuICAgIHR5cGU6IFRlbnNvci5UeXBlLFxuICAgIGRhdGE6IFRlbnNvci5EYXRhVHlwZSB8IHJlYWRvbmx5IG51bWJlcltdIHwgcmVhZG9ubHkgc3RyaW5nW10gfCByZWFkb25seSBiaWdpbnRbXSB8IHJlYWRvbmx5IGJvb2xlYW5bXSxcbiAgICBkaW1zPzogcmVhZG9ubHkgbnVtYmVyW10sXG4gICk6IFRlbnNvcjtcblxuICAvKipcbiAgICogQ29uc3RydWN0IGEgbmV3IHRlbnNvciBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gZGF0YSBhbmQgZGltcy5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBTcGVjaWZ5IHRoZSBDUFUgdGVuc29yIGRhdGEuXG4gICAqIEBwYXJhbSBkaW1zIC0gU3BlY2lmeSB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGEgMS1EIHRlbnNvciBpcyBhc3N1bWVkLlxuICAgKi9cbiAgbmV3IChkYXRhOiBUZW5zb3IuRGF0YVR5cGUsIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSk6IFRlbnNvcjtcbiAgLy8gI2VuZHJlZ2lvblxufVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXG5leHBvcnQgY29uc3QgVGVuc29yID0gVGVuc29ySW1wbCBhcyBUZW5zb3JDb25zdHJ1Y3RvcjtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgZW52IH0gZnJvbSAnLi9lbnYtaW1wbC5qcyc7XG5cbi8qKlxuICogQGlnbm9yZVxuICovXG5leHBvcnQgY29uc3QgVFJBQ0UgPSAoZGV2aWNlVHlwZTogc3RyaW5nLCBsYWJlbDogc3RyaW5nKSA9PiB7XG4gIGlmICh0eXBlb2YgZW52LnRyYWNlID09PSAndW5kZWZpbmVkJyA/ICFlbnYud2FzbS50cmFjZSA6ICFlbnYudHJhY2UpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgY29uc29sZS50aW1lU3RhbXAoYCR7ZGV2aWNlVHlwZX06Ok9SVDo6JHtsYWJlbH1gKTtcbn07XG5cbmNvbnN0IFRSQUNFX0ZVTkMgPSAobXNnOiBzdHJpbmcsIGV4dHJhTXNnPzogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s/LnNwbGl0KC9cXHJcXG58XFxyfFxcbi9nKSB8fCBbXTtcbiAgbGV0IGhhc1RyYWNlRnVuYyA9IGZhbHNlO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0YWNrLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGhhc1RyYWNlRnVuYyAmJiAhc3RhY2tbaV0uaW5jbHVkZXMoJ1RSQUNFX0ZVTkMnKSkge1xuICAgICAgbGV0IGxhYmVsID0gYEZVTkNfJHttc2d9Ojoke3N0YWNrW2ldLnRyaW0oKS5zcGxpdCgnICcpWzFdfWA7XG4gICAgICBpZiAoZXh0cmFNc2cpIHtcbiAgICAgICAgbGFiZWwgKz0gYDo6JHtleHRyYU1zZ31gO1xuICAgICAgfVxuICAgICAgVFJBQ0UoJ0NQVScsIGxhYmVsKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHN0YWNrW2ldLmluY2x1ZGVzKCdUUkFDRV9GVU5DJykpIHtcbiAgICAgIGhhc1RyYWNlRnVuYyA9IHRydWU7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIEBpZ25vcmVcbiAqL1xuZXhwb3J0IGNvbnN0IFRSQUNFX0ZVTkNfQkVHSU4gPSAoZXh0cmFNc2c/OiBzdHJpbmcpID0+IHtcbiAgaWYgKHR5cGVvZiBlbnYudHJhY2UgPT09ICd1bmRlZmluZWQnID8gIWVudi53YXNtLnRyYWNlIDogIWVudi50cmFjZSkge1xuICAgIHJldHVybjtcbiAgfVxuICBUUkFDRV9GVU5DKCdCRUdJTicsIGV4dHJhTXNnKTtcbn07XG5cbi8qKlxuICogQGlnbm9yZVxuICovXG5leHBvcnQgY29uc3QgVFJBQ0VfRlVOQ19FTkQgPSAoZXh0cmFNc2c/OiBzdHJpbmcpID0+IHtcbiAgaWYgKHR5cGVvZiBlbnYudHJhY2UgPT09ICd1bmRlZmluZWQnID8gIWVudi53YXNtLnRyYWNlIDogIWVudi50cmFjZSkge1xuICAgIHJldHVybjtcbiAgfVxuICBUUkFDRV9GVU5DKCdFTkQnLCBleHRyYU1zZyk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyByZXNvbHZlQmFja2VuZEFuZEV4ZWN1dGlvblByb3ZpZGVycyB9IGZyb20gJy4vYmFja2VuZC1pbXBsLmpzJztcbmltcG9ydCB7IEluZmVyZW5jZVNlc3Npb25IYW5kbGVyIH0gZnJvbSAnLi9iYWNrZW5kLmpzJztcbmltcG9ydCB7IEluZmVyZW5jZVNlc3Npb24gYXMgSW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZSB9IGZyb20gJy4vaW5mZXJlbmNlLXNlc3Npb24uanMnO1xuaW1wb3J0IHsgT25ueFZhbHVlIH0gZnJvbSAnLi9vbm54LXZhbHVlLmpzJztcbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJy4vdGVuc29yLmpzJztcbmltcG9ydCB7IFRSQUNFX0ZVTkNfQkVHSU4sIFRSQUNFX0ZVTkNfRU5EIH0gZnJvbSAnLi90cmFjZS5qcyc7XG5cbnR5cGUgU2Vzc2lvbk9wdGlvbnMgPSBJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlLlNlc3Npb25PcHRpb25zO1xudHlwZSBSdW5PcHRpb25zID0gSW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZS5SdW5PcHRpb25zO1xudHlwZSBGZWVkc1R5cGUgPSBJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlLkZlZWRzVHlwZTtcbnR5cGUgRmV0Y2hlc1R5cGUgPSBJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlLkZldGNoZXNUeXBlO1xudHlwZSBSZXR1cm5UeXBlID0gSW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZS5SZXR1cm5UeXBlO1xuXG5leHBvcnQgY2xhc3MgSW5mZXJlbmNlU2Vzc2lvbiBpbXBsZW1lbnRzIEluZmVyZW5jZVNlc3Npb25JbnRlcmZhY2Uge1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKGhhbmRsZXI6IEluZmVyZW5jZVNlc3Npb25IYW5kbGVyKSB7XG4gICAgdGhpcy5oYW5kbGVyID0gaGFuZGxlcjtcbiAgfVxuICBydW4oZmVlZHM6IEZlZWRzVHlwZSwgb3B0aW9ucz86IFJ1bk9wdGlvbnMpOiBQcm9taXNlPFJldHVyblR5cGU+O1xuICBydW4oZmVlZHM6IEZlZWRzVHlwZSwgZmV0Y2hlczogRmV0Y2hlc1R5cGUsIG9wdGlvbnM/OiBSdW5PcHRpb25zKTogUHJvbWlzZTxSZXR1cm5UeXBlPjtcbiAgYXN5bmMgcnVuKGZlZWRzOiBGZWVkc1R5cGUsIGFyZzE/OiBGZXRjaGVzVHlwZSB8IFJ1bk9wdGlvbnMsIGFyZzI/OiBSdW5PcHRpb25zKTogUHJvbWlzZTxSZXR1cm5UeXBlPiB7XG4gICAgVFJBQ0VfRlVOQ19CRUdJTigpO1xuICAgIGNvbnN0IGZldGNoZXM6IHsgW25hbWU6IHN0cmluZ106IE9ubnhWYWx1ZSB8IG51bGwgfSA9IHt9O1xuICAgIGxldCBvcHRpb25zOiBSdW5PcHRpb25zID0ge307XG4gICAgLy8gY2hlY2sgaW5wdXRzXG4gICAgaWYgKHR5cGVvZiBmZWVkcyAhPT0gJ29iamVjdCcgfHwgZmVlZHMgPT09IG51bGwgfHwgZmVlZHMgaW5zdGFuY2VvZiBUZW5zb3IgfHwgQXJyYXkuaXNBcnJheShmZWVkcykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgIFwiJ2ZlZWRzJyBtdXN0IGJlIGFuIG9iamVjdCB0aGF0IHVzZSBpbnB1dCBuYW1lcyBhcyBrZXlzIGFuZCBPbm54VmFsdWUgYXMgY29ycmVzcG9uZGluZyB2YWx1ZXMuXCIsXG4gICAgICApO1xuICAgIH1cblxuICAgIGxldCBpc0ZldGNoZXNFbXB0eSA9IHRydWU7XG4gICAgLy8gZGV0ZXJtaW5lIHdoaWNoIG92ZXJyaWRlIGlzIGJlaW5nIHVzZWRcbiAgICBpZiAodHlwZW9mIGFyZzEgPT09ICdvYmplY3QnKSB7XG4gICAgICBpZiAoYXJnMSA9PT0gbnVsbCkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmV4cGVjdGVkIGFyZ3VtZW50WzFdOiBjYW5ub3QgYmUgbnVsbC4nKTtcbiAgICAgIH1cbiAgICAgIGlmIChhcmcxIGluc3RhbmNlb2YgVGVuc29yKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInZmV0Y2hlcycgY2Fubm90IGJlIGEgVGVuc29yXCIpO1xuICAgICAgfVxuXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShhcmcxKSkge1xuICAgICAgICBpZiAoYXJnMS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiJ2ZldGNoZXMnIGNhbm5vdCBiZSBhbiBlbXB0eSBhcnJheS5cIik7XG4gICAgICAgIH1cbiAgICAgICAgaXNGZXRjaGVzRW1wdHkgPSBmYWxzZTtcbiAgICAgICAgLy8gb3V0cHV0IG5hbWVzXG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBhcmcxKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBuYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIidmZXRjaGVzJyBtdXN0IGJlIGEgc3RyaW5nIGFycmF5IG9yIGFuIG9iamVjdC5cIik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh0aGlzLm91dHB1dE5hbWVzLmluZGV4T2YobmFtZSkgPT09IC0xKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgJ2ZldGNoZXMnIGNvbnRhaW5zIGludmFsaWQgb3V0cHV0IG5hbWU6ICR7bmFtZX0uYCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGZldGNoZXNbbmFtZV0gPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBhcmcyID09PSAnb2JqZWN0JyAmJiBhcmcyICE9PSBudWxsKSB7XG4gICAgICAgICAgb3B0aW9ucyA9IGFyZzI7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC5cIik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGRlY2lkZSB3aGV0aGVyIGFyZzEgaXMgZmV0Y2hlcyBvciBvcHRpb25zXG4gICAgICAgIC8vIGlmIGFueSBvdXRwdXQgbmFtZSBpcyBwcmVzZW50IGFuZCBpdHMgdmFsdWUgaXMgdmFsaWQgT25ueFZhbHVlLCB3ZSBjb25zaWRlciBpdCBmZXRjaGVzXG4gICAgICAgIGxldCBpc0ZldGNoZXMgPSBmYWxzZTtcbiAgICAgICAgY29uc3QgYXJnMUtleXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhhcmcxKTtcbiAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIHRoaXMub3V0cHV0TmFtZXMpIHtcbiAgICAgICAgICBpZiAoYXJnMUtleXMuaW5kZXhPZihuYW1lKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGNvbnN0IHYgPSAoYXJnMSBhcyBJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlLk51bGxhYmxlT25ueFZhbHVlTWFwVHlwZSlbbmFtZV07XG4gICAgICAgICAgICBpZiAodiA9PT0gbnVsbCB8fCB2IGluc3RhbmNlb2YgVGVuc29yKSB7XG4gICAgICAgICAgICAgIGlzRmV0Y2hlcyA9IHRydWU7XG4gICAgICAgICAgICAgIGlzRmV0Y2hlc0VtcHR5ID0gZmFsc2U7XG4gICAgICAgICAgICAgIGZldGNoZXNbbmFtZV0gPSB2O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc0ZldGNoZXMpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGFyZzIgPT09ICdvYmplY3QnICYmIGFyZzIgIT09IG51bGwpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBhcmcyO1xuICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiJ29wdGlvbnMnIG11c3QgYmUgYW4gb2JqZWN0LlwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb3B0aW9ucyA9IGFyZzEgYXMgUnVuT3B0aW9ucztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiVW5leHBlY3RlZCBhcmd1bWVudFsxXTogbXVzdCBiZSAnZmV0Y2hlcycgb3IgJ29wdGlvbnMnLlwiKTtcbiAgICB9XG5cbiAgICAvLyBjaGVjayBpZiBhbGwgaW5wdXRzIGFyZSBpbiBmZWVkXG4gICAgZm9yIChjb25zdCBuYW1lIG9mIHRoaXMuaW5wdXROYW1lcykge1xuICAgICAgaWYgKHR5cGVvZiBmZWVkc1tuYW1lXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnB1dCAnJHtuYW1lfScgaXMgbWlzc2luZyBpbiAnZmVlZHMnLmApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGlmIG5vIGZldGNoZXMgaXMgc3BlY2lmaWVkLCB3ZSB1c2UgdGhlIGZ1bGwgb3V0cHV0IG5hbWVzIGxpc3RcbiAgICBpZiAoaXNGZXRjaGVzRW1wdHkpIHtcbiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiB0aGlzLm91dHB1dE5hbWVzKSB7XG4gICAgICAgIGZldGNoZXNbbmFtZV0gPSBudWxsO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGZlZWRzLCBmZXRjaGVzIGFuZCBvcHRpb25zIGFyZSBwcmVwYXJlZFxuXG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHRoaXMuaGFuZGxlci5ydW4oZmVlZHMsIGZldGNoZXMsIG9wdGlvbnMpO1xuICAgIGNvbnN0IHJldHVyblZhbHVlOiB7IFtuYW1lOiBzdHJpbmddOiBPbm54VmFsdWUgfSA9IHt9O1xuICAgIGZvciAoY29uc3Qga2V5IGluIHJlc3VsdHMpIHtcbiAgICAgIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHRzLCBrZXkpKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHJlc3VsdHNba2V5XTtcbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIFRlbnNvcikge1xuICAgICAgICAgIHJldHVyblZhbHVlW2tleV0gPSByZXN1bHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWVba2V5XSA9IG5ldyBUZW5zb3IocmVzdWx0LnR5cGUsIHJlc3VsdC5kYXRhLCByZXN1bHQuZGltcyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgVFJBQ0VfRlVOQ19FTkQoKTtcbiAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gIH1cblxuICBhc3luYyByZWxlYXNlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLmhhbmRsZXIuZGlzcG9zZSgpO1xuICB9XG5cbiAgc3RhdGljIGNyZWF0ZShwYXRoOiBzdHJpbmcsIG9wdGlvbnM/OiBTZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZT47XG4gIHN0YXRpYyBjcmVhdGUoYnVmZmVyOiBBcnJheUJ1ZmZlckxpa2UsIG9wdGlvbnM/OiBTZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZT47XG4gIHN0YXRpYyBjcmVhdGUoXG4gICAgYnVmZmVyOiBBcnJheUJ1ZmZlckxpa2UsXG4gICAgYnl0ZU9mZnNldDogbnVtYmVyLFxuICAgIGJ5dGVMZW5ndGg/OiBudW1iZXIsXG4gICAgb3B0aW9ucz86IFNlc3Npb25PcHRpb25zLFxuICApOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb25JbnRlcmZhY2U+O1xuICBzdGF0aWMgY3JlYXRlKGJ1ZmZlcjogVWludDhBcnJheSwgb3B0aW9ucz86IFNlc3Npb25PcHRpb25zKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlPjtcbiAgc3RhdGljIGFzeW5jIGNyZWF0ZShcbiAgICBhcmcwOiBzdHJpbmcgfCBBcnJheUJ1ZmZlckxpa2UgfCBVaW50OEFycmF5LFxuICAgIGFyZzE/OiBTZXNzaW9uT3B0aW9ucyB8IG51bWJlcixcbiAgICBhcmcyPzogbnVtYmVyLFxuICAgIGFyZzM/OiBTZXNzaW9uT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uSW50ZXJmYWNlPiB7XG4gICAgVFJBQ0VfRlVOQ19CRUdJTigpO1xuICAgIC8vIGVpdGhlciBsb2FkIGZyb20gYSBmaWxlIG9yIGJ1ZmZlclxuICAgIGxldCBmaWxlUGF0aE9yVWludDhBcnJheTogc3RyaW5nIHwgVWludDhBcnJheTtcbiAgICBsZXQgb3B0aW9uczogU2Vzc2lvbk9wdGlvbnMgPSB7fTtcblxuICAgIGlmICh0eXBlb2YgYXJnMCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGZpbGVQYXRoT3JVaW50OEFycmF5ID0gYXJnMDtcbiAgICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gJ29iamVjdCcgJiYgYXJnMSAhPT0gbnVsbCkge1xuICAgICAgICBvcHRpb25zID0gYXJnMTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuXCIpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoYXJnMCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcbiAgICAgIGZpbGVQYXRoT3JVaW50OEFycmF5ID0gYXJnMDtcbiAgICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gJ29iamVjdCcgJiYgYXJnMSAhPT0gbnVsbCkge1xuICAgICAgICBvcHRpb25zID0gYXJnMTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInb3B0aW9ucycgbXVzdCBiZSBhbiBvYmplY3QuXCIpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoXG4gICAgICBhcmcwIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIgfHxcbiAgICAgICh0eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXIgIT09ICd1bmRlZmluZWQnICYmIGFyZzAgaW5zdGFuY2VvZiBTaGFyZWRBcnJheUJ1ZmZlcilcbiAgICApIHtcbiAgICAgIGNvbnN0IGJ1ZmZlciA9IGFyZzA7XG4gICAgICBsZXQgYnl0ZU9mZnNldCA9IDA7XG4gICAgICBsZXQgYnl0ZUxlbmd0aCA9IGFyZzAuYnl0ZUxlbmd0aDtcbiAgICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gJ29iamVjdCcgJiYgYXJnMSAhPT0gbnVsbCkge1xuICAgICAgICBvcHRpb25zID0gYXJnMTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzEgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGJ5dGVPZmZzZXQgPSBhcmcxO1xuICAgICAgICBpZiAoIU51bWJlci5pc1NhZmVJbnRlZ2VyKGJ5dGVPZmZzZXQpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCInYnl0ZU9mZnNldCcgbXVzdCBiZSBhbiBpbnRlZ2VyLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnl0ZU9mZnNldCA8IDAgfHwgYnl0ZU9mZnNldCA+PSBidWZmZXIuYnl0ZUxlbmd0aCkge1xuICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKGAnYnl0ZU9mZnNldCcgaXMgb3V0IG9mIHJhbmdlIFswLCAke2J1ZmZlci5ieXRlTGVuZ3RofSkuYCk7XG4gICAgICAgIH1cbiAgICAgICAgYnl0ZUxlbmd0aCA9IGFyZzAuYnl0ZUxlbmd0aCAtIGJ5dGVPZmZzZXQ7XG4gICAgICAgIGlmICh0eXBlb2YgYXJnMiA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBieXRlTGVuZ3RoID0gYXJnMjtcbiAgICAgICAgICBpZiAoIU51bWJlci5pc1NhZmVJbnRlZ2VyKGJ5dGVMZW5ndGgpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIidieXRlTGVuZ3RoJyBtdXN0IGJlIGFuIGludGVnZXIuXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoYnl0ZUxlbmd0aCA8PSAwIHx8IGJ5dGVPZmZzZXQgKyBieXRlTGVuZ3RoID4gYnVmZmVyLmJ5dGVMZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKGAnYnl0ZUxlbmd0aCcgaXMgb3V0IG9mIHJhbmdlICgwLCAke2J1ZmZlci5ieXRlTGVuZ3RoIC0gYnl0ZU9mZnNldH1dLmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodHlwZW9mIGFyZzMgPT09ICdvYmplY3QnICYmIGFyZzMgIT09IG51bGwpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBhcmczO1xuICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiJ29wdGlvbnMnIG11c3QgYmUgYW4gb2JqZWN0LlwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZzIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIidieXRlTGVuZ3RoJyBtdXN0IGJlIGEgbnVtYmVyLlwiKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYXJnMSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIidvcHRpb25zJyBtdXN0IGJlIGFuIG9iamVjdC5cIik7XG4gICAgICB9XG4gICAgICBmaWxlUGF0aE9yVWludDhBcnJheSA9IG5ldyBVaW50OEFycmF5KGJ1ZmZlciwgYnl0ZU9mZnNldCwgYnl0ZUxlbmd0aCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJVbmV4cGVjdGVkIGFyZ3VtZW50WzBdOiBtdXN0IGJlICdwYXRoJyBvciAnYnVmZmVyJy5cIik7XG4gICAgfVxuXG4gICAgLy8gcmVzb2x2ZSBiYWNrZW5kLCB1cGRhdGUgc2Vzc2lvbiBvcHRpb25zIHdpdGggdmFsaWRhdGVkIEVQcywgYW5kIGNyZWF0ZSBzZXNzaW9uIGhhbmRsZXJcbiAgICBjb25zdCBbYmFja2VuZCwgb3B0aW9uc1dpdGhWYWxpZGF0ZWRFUHNdID0gYXdhaXQgcmVzb2x2ZUJhY2tlbmRBbmRFeGVjdXRpb25Qcm92aWRlcnMob3B0aW9ucyk7XG4gICAgY29uc3QgaGFuZGxlciA9IGF3YWl0IGJhY2tlbmQuY3JlYXRlSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIoZmlsZVBhdGhPclVpbnQ4QXJyYXksIG9wdGlvbnNXaXRoVmFsaWRhdGVkRVBzKTtcbiAgICBUUkFDRV9GVU5DX0VORCgpO1xuICAgIHJldHVybiBuZXcgSW5mZXJlbmNlU2Vzc2lvbihoYW5kbGVyKTtcbiAgfVxuXG4gIHN0YXJ0UHJvZmlsaW5nKCk6IHZvaWQge1xuICAgIHRoaXMuaGFuZGxlci5zdGFydFByb2ZpbGluZygpO1xuICB9XG4gIGVuZFByb2ZpbGluZygpOiB2b2lkIHtcbiAgICB0aGlzLmhhbmRsZXIuZW5kUHJvZmlsaW5nKCk7XG4gIH1cblxuICBnZXQgaW5wdXROYW1lcygpOiByZWFkb25seSBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuaGFuZGxlci5pbnB1dE5hbWVzO1xuICB9XG4gIGdldCBvdXRwdXROYW1lcygpOiByZWFkb25seSBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuaGFuZGxlci5vdXRwdXROYW1lcztcbiAgfVxuXG4gIGdldCBpbnB1dE1ldGFkYXRhKCk6IHJlYWRvbmx5IEluZmVyZW5jZVNlc3Npb25JbnRlcmZhY2UuVmFsdWVNZXRhZGF0YVtdIHtcbiAgICByZXR1cm4gdGhpcy5oYW5kbGVyLmlucHV0TWV0YWRhdGE7XG4gIH1cblxuICBnZXQgb3V0cHV0TWV0YWRhdGEoKTogcmVhZG9ubHkgSW5mZXJlbmNlU2Vzc2lvbkludGVyZmFjZS5WYWx1ZU1ldGFkYXRhW10ge1xuICAgIHJldHVybiB0aGlzLmhhbmRsZXIub3V0cHV0TWV0YWRhdGE7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZXI6IEluZmVyZW5jZVNlc3Npb25IYW5kbGVyO1xufVxuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBJbmZlcmVuY2VTZXNzaW9uIGFzIEluZmVyZW5jZVNlc3Npb25JbXBsIH0gZnJvbSAnLi9pbmZlcmVuY2Utc2Vzc2lvbi1pbXBsLmpzJztcbmltcG9ydCB7IE9ubnhNb2RlbE9wdGlvbnMgfSBmcm9tICcuL29ubngtbW9kZWwuanMnO1xuaW1wb3J0IHsgT25ueFZhbHVlLCBPbm54VmFsdWVEYXRhTG9jYXRpb24gfSBmcm9tICcuL29ubngtdmFsdWUuanMnO1xuaW1wb3J0IHR5cGUgeyBUZW5zb3IgfSBmcm9tICcuL3RlbnNvci5qcyc7XG5pbXBvcnQgeyBUcnlHZXRHbG9iYWxUeXBlIH0gZnJvbSAnLi90eXBlLWhlbHBlci5qcyc7XG5cbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZWRlY2xhcmUgKi9cblxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIEluZmVyZW5jZVNlc3Npb24ge1xuICAvLyAjcmVnaW9uIGlucHV0L291dHB1dCB0eXBlc1xuXG4gIHR5cGUgT25ueFZhbHVlTWFwVHlwZSA9IHsgcmVhZG9ubHkgW25hbWU6IHN0cmluZ106IE9ubnhWYWx1ZSB9O1xuICB0eXBlIE51bGxhYmxlT25ueFZhbHVlTWFwVHlwZSA9IHsgcmVhZG9ubHkgW25hbWU6IHN0cmluZ106IE9ubnhWYWx1ZSB8IG51bGwgfTtcblxuICAvKipcbiAgICogQSBmZWVkcyAobW9kZWwgaW5wdXRzKSBpcyBhbiBvYmplY3QgdGhhdCB1c2VzIGlucHV0IG5hbWVzIGFzIGtleXMgYW5kIE9ubnhWYWx1ZSBhcyBjb3JyZXNwb25kaW5nIHZhbHVlcy5cbiAgICovXG4gIHR5cGUgRmVlZHNUeXBlID0gT25ueFZhbHVlTWFwVHlwZTtcblxuICAvKipcbiAgICogQSBmZXRjaGVzIChtb2RlbCBvdXRwdXRzKSBjb3VsZCBiZSBvbmUgb2YgdGhlIGZvbGxvd2luZzpcbiAgICpcbiAgICogLSBPbWl0dGVkLiBVc2UgbW9kZWwncyBvdXRwdXQgbmFtZXMgZGVmaW5pdGlvbi5cbiAgICogLSBBbiBhcnJheSBvZiBzdHJpbmcgaW5kaWNhdGluZyB0aGUgb3V0cHV0IG5hbWVzLlxuICAgKiAtIEFuIG9iamVjdCB0aGF0IHVzZSBvdXRwdXQgbmFtZXMgYXMga2V5cyBhbmQgT25ueFZhbHVlIG9yIG51bGwgYXMgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAqXG4gICAqIEByZW1hcmtcbiAgICogZGlmZmVyZW50IGZyb20gaW5wdXQgYXJndW1lbnQsIGluIG91dHB1dCwgT25ueFZhbHVlIGlzIG9wdGlvbmFsLiBJZiBhbiBPbm54VmFsdWUgaXMgcHJlc2VudCBpdCB3aWxsIGJlXG4gICAqIHVzZWQgYXMgYSBwcmUtYWxsb2NhdGVkIHZhbHVlIGJ5IHRoZSBpbmZlcmVuY2UgZW5naW5lOyBpZiBvbWl0dGVkLCBpbmZlcmVuY2UgZW5naW5lIHdpbGwgYWxsb2NhdGUgYnVmZmVyXG4gICAqIGludGVybmFsbHkuXG4gICAqL1xuICB0eXBlIEZldGNoZXNUeXBlID0gcmVhZG9ubHkgc3RyaW5nW10gfCBOdWxsYWJsZU9ubnhWYWx1ZU1hcFR5cGU7XG5cbiAgLyoqXG4gICAqIEEgaW5mZXJlbmNpbmcgcmV0dXJuIHR5cGUgaXMgYW4gb2JqZWN0IHRoYXQgdXNlcyBvdXRwdXQgbmFtZXMgYXMga2V5cyBhbmQgT25ueFZhbHVlIGFzIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICAgKi9cbiAgdHlwZSBSZXR1cm5UeXBlID0gT25ueFZhbHVlTWFwVHlwZTtcblxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBzZXNzaW9uIG9wdGlvbnNcblxuICAvKipcbiAgICogQSBzZXQgb2YgY29uZmlndXJhdGlvbnMgZm9yIHNlc3Npb24gYmVoYXZpb3IuXG4gICAqL1xuICBleHBvcnQgaW50ZXJmYWNlIFNlc3Npb25PcHRpb25zIGV4dGVuZHMgT25ueE1vZGVsT3B0aW9ucyB7XG4gICAgLyoqXG4gICAgICogQW4gYXJyYXkgb2YgZXhlY3V0aW9uIHByb3ZpZGVyIG9wdGlvbnMuXG4gICAgICpcbiAgICAgKiBBbiBleGVjdXRpb24gcHJvdmlkZXIgb3B0aW9uIGNhbiBiZSBhIHN0cmluZyBpbmRpY2F0aW5nIHRoZSBuYW1lIG9mIHRoZSBleGVjdXRpb24gcHJvdmlkZXIsXG4gICAgICogb3IgYW4gb2JqZWN0IG9mIGNvcnJlc3BvbmRpbmcgdHlwZS5cbiAgICAgKi9cbiAgICBleGVjdXRpb25Qcm92aWRlcnM/OiByZWFkb25seSBFeGVjdXRpb25Qcm92aWRlckNvbmZpZ1tdO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGludHJhIE9QIHRocmVhZHMgbnVtYmVyLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSkuXG4gICAgICovXG4gICAgaW50cmFPcE51bVRocmVhZHM/OiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgaW50ZXIgT1AgdGhyZWFkcyBudW1iZXIuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlKS5cbiAgICAgKi9cbiAgICBpbnRlck9wTnVtVGhyZWFkcz86IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBmcmVlIGRpbWVuc2lvbiBvdmVycmlkZS5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAoTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUpIG9yIFdlYkFzc2VtYmx5IGJhY2tlbmRcbiAgICAgKi9cbiAgICBmcmVlRGltZW5zaW9uT3ZlcnJpZGVzPzogeyByZWFkb25seSBbZGltZW5zaW9uTmFtZTogc3RyaW5nXTogbnVtYmVyIH07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3B0aW1pemF0aW9uIGxldmVsLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSkgb3IgV2ViQXNzZW1ibHkgYmFja2VuZFxuICAgICAqL1xuICAgIGdyYXBoT3B0aW1pemF0aW9uTGV2ZWw/OiAnZGlzYWJsZWQnIHwgJ2Jhc2ljJyB8ICdleHRlbmRlZCcgfCAnYWxsJztcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgZW5hYmxlIENQVSBtZW1vcnkgYXJlbmEuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlKSBvciBXZWJBc3NlbWJseSBiYWNrZW5kXG4gICAgICovXG4gICAgZW5hYmxlQ3B1TWVtQXJlbmE/OiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciBlbmFibGUgbWVtb3J5IHBhdHRlcm4uXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlKSBvciBXZWJBc3NlbWJseSBiYWNrZW5kXG4gICAgICovXG4gICAgZW5hYmxlTWVtUGF0dGVybj86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBFeGVjdXRpb24gbW9kZS5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAoTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUpIG9yIFdlYkFzc2VtYmx5IGJhY2tlbmRcbiAgICAgKi9cbiAgICBleGVjdXRpb25Nb2RlPzogJ3NlcXVlbnRpYWwnIHwgJ3BhcmFsbGVsJztcblxuICAgIC8qKlxuICAgICAqIE9wdGltaXplZCBtb2RlbCBmaWxlIHBhdGguXG4gICAgICpcbiAgICAgKiBJZiB0aGlzIHNldHRpbmcgaXMgc3BlY2lmaWVkLCB0aGUgb3B0aW1pemVkIG1vZGVsIHdpbGwgYmUgZHVtcGVkLiBJbiBicm93c2VyLCBhIGJsb2Igd2lsbCBiZSBjcmVhdGVkXG4gICAgICogd2l0aCBhIHBvcC11cCB3aW5kb3cuXG4gICAgICovXG4gICAgb3B0aW1pemVkTW9kZWxGaWxlUGF0aD86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgZW5hYmxlIHByb2ZpbGluZy5cbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhIHBsYWNlaG9sZGVyIGZvciBhIGZ1dHVyZSB1c2UuXG4gICAgICovXG4gICAgZW5hYmxlUHJvZmlsaW5nPzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIEZpbGUgcHJlZml4IGZvciBwcm9maWxpbmcuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYSBwbGFjZWhvbGRlciBmb3IgYSBmdXR1cmUgdXNlLlxuICAgICAqL1xuICAgIHByb2ZpbGVGaWxlUHJlZml4Pzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogTG9nIElELlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSkgb3IgV2ViQXNzZW1ibHkgYmFja2VuZFxuICAgICAqL1xuICAgIGxvZ0lkPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogTG9nIHNldmVyaXR5IGxldmVsLiBTZWVcbiAgICAgKiBodHRwczovL2dpdGh1Yi5jb20vbWljcm9zb2Z0L29ubnhydW50aW1lL2Jsb2IvbWFpbi9pbmNsdWRlL29ubnhydW50aW1lL2NvcmUvY29tbW9uL2xvZ2dpbmcvc2V2ZXJpdHkuaFxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSkgb3IgV2ViQXNzZW1ibHkgYmFja2VuZFxuICAgICAqL1xuICAgIGxvZ1NldmVyaXR5TGV2ZWw/OiAwIHwgMSB8IDIgfCAzIHwgNDtcblxuICAgIC8qKlxuICAgICAqIExvZyB2ZXJib3NpdHkgbGV2ZWwuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gV2ViQXNzZW1ibHkgYmFja2VuZC4gV2lsbCBzdXBwb3J0IE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlIGxhdGVyXG4gICAgICovXG4gICAgbG9nVmVyYm9zaXR5TGV2ZWw/OiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBTcGVjaWZ5IHN0cmluZyBhcyBhIHByZWZlcnJlZCBkYXRhIGxvY2F0aW9uIGZvciBhbGwgb3V0cHV0cywgb3IgYW4gb2JqZWN0IHRoYXQgdXNlIG91dHB1dCBuYW1lcyBhcyBrZXlzIGFuZCBhXG4gICAgICogcHJlZmVycmVkIGRhdGEgbG9jYXRpb24gYXMgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgV2ViIGZvciBXZWJHTCBhbmQgV2ViR1BVIEVQLlxuICAgICAqL1xuICAgIHByZWZlcnJlZE91dHB1dExvY2F0aW9uPzogT25ueFZhbHVlRGF0YUxvY2F0aW9uIHwgeyByZWFkb25seSBbb3V0cHV0TmFtZTogc3RyaW5nXTogT25ueFZhbHVlRGF0YUxvY2F0aW9uIH07XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIGVuYWJsZSBncmFwaCBjYXB0dXJlLlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSBXZWIgZm9yIFdlYkdQVSBFUC5cbiAgICAgKi9cbiAgICBlbmFibGVHcmFwaENhcHR1cmU/OiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogU3RvcmUgY29uZmlndXJhdGlvbnMgZm9yIGEgc2Vzc2lvbi4gU2VlXG4gICAgICogaHR0cHM6Ly9naXRodWIuY29tL21pY3Jvc29mdC9vbm54cnVudGltZS9ibG9iL21haW4vaW5jbHVkZS9vbm54cnVudGltZS9jb3JlL3Nlc3Npb24vXG4gICAgICogb25ueHJ1bnRpbWVfc2Vzc2lvbl9vcHRpb25zX2NvbmZpZ19rZXlzLmhcbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBXZWJBc3NlbWJseSBiYWNrZW5kLiBXaWxsIHN1cHBvcnQgTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUgbGF0ZXJcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBleHRyYToge1xuICAgICAqICAgc2Vzc2lvbjoge1xuICAgICAqICAgICBzZXRfZGVub3JtYWxfYXNfemVybzogXCIxXCIsXG4gICAgICogICAgIGRpc2FibGVfcHJlcGFja2luZzogXCIxXCJcbiAgICAgKiAgIH0sXG4gICAgICogICBvcHRpbWl6YXRpb246IHtcbiAgICAgKiAgICAgZW5hYmxlX2dlbHVfYXBwcm94aW1hdGlvbjogXCIxXCJcbiAgICAgKiAgIH1cbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZXh0cmE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgfVxuXG4gIC8vICNyZWdpb24gZXhlY3V0aW9uIHByb3ZpZGVyc1xuXG4gIC8vIEN1cnJlbnRseSwgd2UgaGF2ZSB0aGUgZm9sbG93aW5nIGJhY2tlbmRzIHRvIHN1cHBvcnQgZXhlY3V0aW9uIHByb3ZpZGVyczpcbiAgLy8gQmFja2VuZCBOb2RlLmpzIGJpbmRpbmc6IHN1cHBvcnRzICdjcHUnLCAnZG1sJyAod2luMzIpLCAnY29yZW1sJyAobWFjT1MpIGFuZCAnY3VkYScgKGxpbnV4KS5cbiAgLy8gQmFja2VuZCBXZWJBc3NlbWJseTogc3VwcG9ydHMgJ2NwdScsICd3YXNtJywgJ3dlYmdwdScgYW5kICd3ZWJubicuXG4gIC8vIEJhY2tlbmQgT05OWC5qczogc3VwcG9ydHMgJ3dlYmdsJy5cbiAgLy8gQmFja2VuZCBSZWFjdCBOYXRpdmU6IHN1cHBvcnRzICdjcHUnLCAneG5ucGFjaycsICdjb3JlbWwnIChpT1MpLCAnbm5hcGknIChBbmRyb2lkKS5cbiAgaW50ZXJmYWNlIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uTWFwIHtcbiAgICBjb3JlbWw6IENvcmVNTEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIGNwdTogQ3B1RXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgY3VkYTogQ3VkYUV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIGRtbDogRG1sRXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgbm5hcGk6IE5uYXBpRXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgdGVuc29ycnQ6IFRlbnNvclJ0RXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgd2FzbTogV2ViQXNzZW1ibHlFeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICB3ZWJnbDogV2ViR0xFeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICB3ZWJncHU6IFdlYkdwdUV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIHdlYm5uOiBXZWJOTkV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgIHFubjogUW5uRXhlY3V0aW9uUHJvdmlkZXJPcHRpb247XG4gICAgeG5ucGFjazogWG5ucGFja0V4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICB9XG5cbiAgdHlwZSBFeGVjdXRpb25Qcm92aWRlck5hbWUgPSBrZXlvZiBFeGVjdXRpb25Qcm92aWRlck9wdGlvbk1hcDtcbiAgdHlwZSBFeGVjdXRpb25Qcm92aWRlckNvbmZpZyA9XG4gICAgfCBFeGVjdXRpb25Qcm92aWRlck9wdGlvbk1hcFtFeGVjdXRpb25Qcm92aWRlck5hbWVdXG4gICAgfCBFeGVjdXRpb25Qcm92aWRlck9wdGlvblxuICAgIHwgRXhlY3V0aW9uUHJvdmlkZXJOYW1lXG4gICAgfCBzdHJpbmc7XG5cbiAgZXhwb3J0IGludGVyZmFjZSBFeGVjdXRpb25Qcm92aWRlck9wdGlvbiB7XG4gICAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuICB9XG4gIGV4cG9ydCBpbnRlcmZhY2UgQ3B1RXhlY3V0aW9uUHJvdmlkZXJPcHRpb24gZXh0ZW5kcyBFeGVjdXRpb25Qcm92aWRlck9wdGlvbiB7XG4gICAgcmVhZG9ubHkgbmFtZTogJ2NwdSc7XG4gICAgdXNlQXJlbmE/OiBib29sZWFuO1xuICB9XG4gIGV4cG9ydCBpbnRlcmZhY2UgQ3VkYUV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICdjdWRhJztcbiAgICBkZXZpY2VJZD86IG51bWJlcjtcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIERtbEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICdkbWwnO1xuICAgIGRldmljZUlkPzogbnVtYmVyO1xuICB9XG4gIGV4cG9ydCBpbnRlcmZhY2UgVGVuc29yUnRFeGVjdXRpb25Qcm92aWRlck9wdGlvbiBleHRlbmRzIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIHtcbiAgICByZWFkb25seSBuYW1lOiAndGVuc29ycnQnO1xuICAgIGRldmljZUlkPzogbnVtYmVyO1xuICB9XG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViQXNzZW1ibHlFeGVjdXRpb25Qcm92aWRlck9wdGlvbiBleHRlbmRzIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIHtcbiAgICByZWFkb25seSBuYW1lOiAnd2FzbSc7XG4gIH1cbiAgZXhwb3J0IGludGVyZmFjZSBXZWJHTEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICd3ZWJnbCc7XG4gICAgLy8gVE9ETzogYWRkIGZsYWdzXG4gIH1cbiAgZXhwb3J0IGludGVyZmFjZSBYbm5wYWNrRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24gZXh0ZW5kcyBFeGVjdXRpb25Qcm92aWRlck9wdGlvbiB7XG4gICAgcmVhZG9ubHkgbmFtZTogJ3hubnBhY2snO1xuICB9XG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViR3B1RXhlY3V0aW9uUHJvdmlkZXJPcHRpb24gZXh0ZW5kcyBFeGVjdXRpb25Qcm92aWRlck9wdGlvbiB7XG4gICAgcmVhZG9ubHkgbmFtZTogJ3dlYmdwdSc7XG4gICAgcHJlZmVycmVkTGF5b3V0PzogJ05DSFcnIHwgJ05IV0MnO1xuICB9XG5cbiAgLy8gI3JlZ2lvbiBXZWJOTiBvcHRpb25zXG5cbiAgaW50ZXJmYWNlIFdlYk5ORXhlY3V0aW9uUHJvdmlkZXJOYW1lIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICd3ZWJubic7XG4gIH1cblxuICAvKipcbiAgICogUmVwcmVzZW50cyBhIHNldCBvZiBvcHRpb25zIGZvciBjcmVhdGluZyBhIFdlYk5OIE1MQ29udGV4dC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL3d3dy53My5vcmcvVFIvd2Vibm4vI2RpY3RkZWYtbWxjb250ZXh0b3B0aW9uc1xuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBXZWJOTkNvbnRleHRPcHRpb25zIHtcbiAgICBkZXZpY2VUeXBlPzogJ2NwdScgfCAnZ3B1JyB8ICducHUnO1xuICAgIG51bVRocmVhZHM/OiBudW1iZXI7XG4gICAgcG93ZXJQcmVmZXJlbmNlPzogJ2RlZmF1bHQnIHwgJ2xvdy1wb3dlcicgfCAnaGlnaC1wZXJmb3JtYW5jZSc7XG4gIH1cblxuICAvKipcbiAgICogUmVwcmVzZW50cyBhIHNldCBvZiBvcHRpb25zIGZvciBXZWJOTiBleGVjdXRpb24gcHJvdmlkZXIgd2l0aG91dCBNTENvbnRleHQuXG4gICAqL1xuICBleHBvcnQgaW50ZXJmYWNlIFdlYk5OT3B0aW9uc1dpdGhvdXRNTENvbnRleHQgZXh0ZW5kcyBXZWJOTkV4ZWN1dGlvblByb3ZpZGVyTmFtZSwgV2ViTk5Db250ZXh0T3B0aW9ucyB7XG4gICAgY29udGV4dD86IG5ldmVyO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudHMgYSBzZXQgb2Ygb3B0aW9ucyBmb3IgV2ViTk4gZXhlY3V0aW9uIHByb3ZpZGVyIHdpdGggTUxDb250ZXh0LlxuICAgKlxuICAgKiBXaGVuIE1MQ29udGV4dCBpcyBwcm92aWRlZCwgdGhlIGRldmljZVR5cGUgaXMgYWxzbyByZXF1aXJlZCBzbyB0aGF0IHRoZSBXZWJOTiBFUCBjYW4gZGV0ZXJtaW5lIHRoZSBwcmVmZXJyZWRcbiAgICogY2hhbm5lbCBsYXlvdXQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly93d3cudzMub3JnL1RSL3dlYm5uLyNkb20tbWwtY3JlYXRlY29udGV4dFxuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBXZWJOTk9wdGlvbnNXaXRoTUxDb250ZXh0XG4gICAgZXh0ZW5kcyBXZWJOTkV4ZWN1dGlvblByb3ZpZGVyTmFtZSxcbiAgICAgIE9taXQ8V2ViTk5Db250ZXh0T3B0aW9ucywgJ2RldmljZVR5cGUnPixcbiAgICAgIFJlcXVpcmVkPFBpY2s8V2ViTk5Db250ZXh0T3B0aW9ucywgJ2RldmljZVR5cGUnPj4ge1xuICAgIGNvbnRleHQ6IFRyeUdldEdsb2JhbFR5cGU8J01MQ29udGV4dCc+O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudHMgYSBzZXQgb2Ygb3B0aW9ucyBmb3IgV2ViTk4gZXhlY3V0aW9uIHByb3ZpZGVyIHdpdGggTUxDb250ZXh0IHdoaWNoIGlzIGNyZWF0ZWQgZnJvbSBHUFVEZXZpY2UuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly93d3cudzMub3JnL1RSL3dlYm5uLyNkb20tbWwtY3JlYXRlY29udGV4dC1ncHVkZXZpY2VcbiAgICovXG4gIGV4cG9ydCBpbnRlcmZhY2UgV2ViTk5PcHRpb25zV2ViR3B1IGV4dGVuZHMgV2ViTk5FeGVjdXRpb25Qcm92aWRlck5hbWUge1xuICAgIGNvbnRleHQ6IFRyeUdldEdsb2JhbFR5cGU8J01MQ29udGV4dCc+O1xuICAgIGdwdURldmljZTogVHJ5R2V0R2xvYmFsVHlwZTwnR1BVRGV2aWNlJz47XG4gIH1cblxuICAvKipcbiAgICogT3B0aW9ucyBmb3IgV2ViTk4gZXhlY3V0aW9uIHByb3ZpZGVyLlxuICAgKi9cbiAgZXhwb3J0IHR5cGUgV2ViTk5FeGVjdXRpb25Qcm92aWRlck9wdGlvbiA9XG4gICAgfCBXZWJOTk9wdGlvbnNXaXRob3V0TUxDb250ZXh0XG4gICAgfCBXZWJOTk9wdGlvbnNXaXRoTUxDb250ZXh0XG4gICAgfCBXZWJOTk9wdGlvbnNXZWJHcHU7XG5cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIGV4cG9ydCBpbnRlcmZhY2UgUW5uRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24gZXh0ZW5kcyBFeGVjdXRpb25Qcm92aWRlck9wdGlvbiB7XG4gICAgcmVhZG9ubHkgbmFtZTogJ3Fubic7XG4gICAgLyoqXG4gICAgICogU3BlY2lmeSB0aGUgUU5OIGJhY2tlbmQgdHlwZS4gRS5nLiwgJ2NwdScgb3IgJ2h0cCcuXG4gICAgICogTXV0dWFsbHkgZXhjbHVzaXZlIHdpdGggYGJhY2tlbmRQYXRoYC5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0ICdodHAnXG4gICAgICovXG4gICAgYmFja2VuZFR5cGU/OiBzdHJpbmc7XG4gICAgLyoqXG4gICAgICogU3BlY2lmeSBhIHBhdGggdG8gdGhlIFFOTiBiYWNrZW5kIGxpYnJhcnkuXG4gICAgICogTXV0dWFsbHkgZXhjbHVzaXZlIHdpdGggYGJhY2tlbmRUeXBlYC5cbiAgICAgKi9cbiAgICBiYWNrZW5kUGF0aD86IHN0cmluZztcbiAgICAvKipcbiAgICAgKiBTcGVjaWZ5IHdoZXRoZXIgdG8gZW5hYmxlIEhUUCBGUDE2IHByZWNpc2lvbi5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0IHRydWVcbiAgICAgKi9cbiAgICBlbmFibGVGcDE2UHJlY2lzaW9uPzogYm9vbGVhbjtcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIENvcmVNTEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIGV4dGVuZHMgRXhlY3V0aW9uUHJvdmlkZXJPcHRpb24ge1xuICAgIHJlYWRvbmx5IG5hbWU6ICdjb3JlbWwnO1xuICAgIC8qKlxuICAgICAqIFRoZSBiaXQgZmxhZ3MgZm9yIENvcmVNTCBleGVjdXRpb24gcHJvdmlkZXIuXG4gICAgICpcbiAgICAgKiBgYGBcbiAgICAgKiBDT1JFTUxfRkxBR19VU0VfQ1BVX09OTFkgPSAweDAwMVxuICAgICAqIENPUkVNTF9GTEFHX0VOQUJMRV9PTl9TVUJHUkFQSCA9IDB4MDAyXG4gICAgICogQ09SRU1MX0ZMQUdfT05MWV9FTkFCTEVfREVWSUNFX1dJVEhfQU5FID0gMHgwMDRcbiAgICAgKiBDT1JFTUxfRkxBR19PTkxZX0FMTE9XX1NUQVRJQ19JTlBVVF9TSEFQRVMgPSAweDAwOFxuICAgICAqIENPUkVNTF9GTEFHX0NSRUFURV9NTFBST0dSQU0gPSAweDAxMFxuICAgICAqIENPUkVNTF9GTEFHX1VTRV9DUFVfQU5EX0dQVSA9IDB4MDIwXG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBTZWUgaW5jbHVkZS9vbm54cnVudGltZS9jb3JlL3Byb3ZpZGVycy9jb3JlbWwvY29yZW1sX3Byb3ZpZGVyX2ZhY3RvcnkuaCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogVGhpcyBmbGFnIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcpLlxuICAgICAqL1xuICAgIGNvcmVNbEZsYWdzPzogbnVtYmVyO1xuICAgIC8qKlxuICAgICAqIFNwZWNpZnkgd2hldGhlciB0byB1c2UgQ1BVIG9ubHkgaW4gQ29yZU1MIEVQLlxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChyZWFjdC1uYXRpdmUpLlxuICAgICAqL1xuICAgIHVzZUNQVU9ubHk/OiBib29sZWFuO1xuICAgIHVzZUNQVUFuZEdQVT86IGJvb2xlYW47XG4gICAgLyoqXG4gICAgICogU3BlY2lmeSB3aGV0aGVyIHRvIGVuYWJsZSBDb3JlTUwgRVAgb24gc3ViZ3JhcGguXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKHJlYWN0LW5hdGl2ZSkuXG4gICAgICovXG4gICAgZW5hYmxlT25TdWJncmFwaD86IGJvb2xlYW47XG4gICAgLyoqXG4gICAgICogU3BlY2lmeSB3aGV0aGVyIHRvIG9ubHkgZW5hYmxlIENvcmVNTCBFUCBmb3IgQXBwbGUgZGV2aWNlcyB3aXRoIEFORSAoQXBwbGUgTmV1cmFsIEVuZ2luZSkuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gT05OWFJ1bnRpbWUgKHJlYWN0LW5hdGl2ZSkuXG4gICAgICovXG4gICAgb25seUVuYWJsZURldmljZVdpdGhBTkU/OiBib29sZWFuO1xuICB9XG4gIGV4cG9ydCBpbnRlcmZhY2UgTm5hcGlFeGVjdXRpb25Qcm92aWRlck9wdGlvbiBleHRlbmRzIEV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uIHtcbiAgICByZWFkb25seSBuYW1lOiAnbm5hcGknO1xuICAgIHVzZUZQMTY/OiBib29sZWFuO1xuICAgIHVzZU5DSFc/OiBib29sZWFuO1xuICAgIGNwdURpc2FibGVkPzogYm9vbGVhbjtcbiAgICBjcHVPbmx5PzogYm9vbGVhbjtcbiAgfVxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gcnVuIG9wdGlvbnNcblxuICAvKipcbiAgICogQSBzZXQgb2YgY29uZmlndXJhdGlvbnMgZm9yIGluZmVyZW5jZSBydW4gYmVoYXZpb3JcbiAgICovXG4gIGV4cG9ydCBpbnRlcmZhY2UgUnVuT3B0aW9ucyB7XG4gICAgLyoqXG4gICAgICogTG9nIHNldmVyaXR5IGxldmVsLiBTZWVcbiAgICAgKiBodHRwczovL2dpdGh1Yi5jb20vbWljcm9zb2Z0L29ubnhydW50aW1lL2Jsb2IvbWFpbi9pbmNsdWRlL29ubnhydW50aW1lL2NvcmUvY29tbW9uL2xvZ2dpbmcvc2V2ZXJpdHkuaFxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIE9OTlhSdW50aW1lIChOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSkgb3IgV2ViQXNzZW1ibHkgYmFja2VuZFxuICAgICAqL1xuICAgIGxvZ1NldmVyaXR5TGV2ZWw/OiAwIHwgMSB8IDIgfCAzIHwgNDtcblxuICAgIC8qKlxuICAgICAqIExvZyB2ZXJib3NpdHkgbGV2ZWwuXG4gICAgICpcbiAgICAgKiBUaGlzIHNldHRpbmcgaXMgYXZhaWxhYmxlIG9ubHkgaW4gV2ViQXNzZW1ibHkgYmFja2VuZC4gV2lsbCBzdXBwb3J0IE5vZGUuanMgYmluZGluZyBhbmQgcmVhY3QtbmF0aXZlIGxhdGVyXG4gICAgICovXG4gICAgbG9nVmVyYm9zaXR5TGV2ZWw/OiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBUZXJtaW5hdGUgYWxsIGluY29tcGxldGUgT3J0UnVuIGNhbGxzIGFzIHNvb24gYXMgcG9zc2libGUgaWYgdHJ1ZVxuICAgICAqXG4gICAgICogVGhpcyBzZXR0aW5nIGlzIGF2YWlsYWJsZSBvbmx5IGluIFdlYkFzc2VtYmx5IGJhY2tlbmQuIFdpbGwgc3VwcG9ydCBOb2RlLmpzIGJpbmRpbmcgYW5kIHJlYWN0LW5hdGl2ZSBsYXRlclxuICAgICAqL1xuICAgIHRlcm1pbmF0ZT86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBBIHRhZyBmb3IgdGhlIFJ1bigpIGNhbGxzIHVzaW5nIHRoaXNcbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBPTk5YUnVudGltZSAoTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUpIG9yIFdlYkFzc2VtYmx5IGJhY2tlbmRcbiAgICAgKi9cbiAgICB0YWc/OiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBTZXQgYSBzaW5nbGUgcnVuIGNvbmZpZ3VyYXRpb24gZW50cnkuIFNlZVxuICAgICAqIGh0dHBzOi8vZ2l0aHViLmNvbS9taWNyb3NvZnQvb25ueHJ1bnRpbWUvYmxvYi9tYWluL2luY2x1ZGUvb25ueHJ1bnRpbWUvY29yZS9zZXNzaW9uL1xuICAgICAqIG9ubnhydW50aW1lX3J1bl9vcHRpb25zX2NvbmZpZ19rZXlzLmhcbiAgICAgKlxuICAgICAqIFRoaXMgc2V0dGluZyBpcyBhdmFpbGFibGUgb25seSBpbiBXZWJBc3NlbWJseSBiYWNrZW5kLiBXaWxsIHN1cHBvcnQgTm9kZS5qcyBiaW5kaW5nIGFuZCByZWFjdC1uYXRpdmUgbGF0ZXJcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGV4dHJhOiB7XG4gICAgICogICBtZW1vcnk6IHtcbiAgICAgKiAgICAgZW5hYmxlX21lbW9yeV9hcmVuYV9zaHJpbmthZ2U6IFwiMVwiLFxuICAgICAqICAgfVxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBleHRyYT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICB9XG5cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIC8vICNyZWdpb24gdmFsdWUgbWV0YWRhdGFcblxuICAvKipcbiAgICogVGhlIGNvbW1vbiBwYXJ0IG9mIHRoZSB2YWx1ZSBtZXRhZGF0YSB0eXBlIGZvciBib3RoIHRlbnNvciBhbmQgbm9uLXRlbnNvciB2YWx1ZXMuXG4gICAqL1xuICBleHBvcnQgaW50ZXJmYWNlIFZhbHVlTWV0YWRhdGFCYXNlIHtcbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgc3BlY2lmaWVkIGlucHV0IG9yIG91dHB1dC5cbiAgICAgKi9cbiAgICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gIH1cblxuICAvKipcbiAgICogUmVwcmVzZW50cyB0aGUgbWV0YWRhdGEgb2YgYSBub24tdGVuc29yIHZhbHVlLlxuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBOb25UZW5zb3JWYWx1ZU1ldGFkYXRhIGV4dGVuZHMgVmFsdWVNZXRhZGF0YUJhc2Uge1xuICAgIC8qKlxuICAgICAqIEdldCBhIHZhbHVlIGluZGljYXRpbmcgd2hldGhlciB0aGUgdmFsdWUgaXMgYSB0ZW5zb3IuXG4gICAgICovXG4gICAgcmVhZG9ubHkgaXNUZW5zb3I6IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudHMgdGhlIG1ldGFkYXRhIG9mIGEgdGVuc29yIHZhbHVlLlxuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBUZW5zb3JWYWx1ZU1ldGFkYXRhIGV4dGVuZHMgVmFsdWVNZXRhZGF0YUJhc2Uge1xuICAgIC8qKlxuICAgICAqIEdldCBhIHZhbHVlIGluZGljYXRpbmcgd2hldGhlciB0aGUgdmFsdWUgaXMgYSB0ZW5zb3IuXG4gICAgICovXG4gICAgcmVhZG9ubHkgaXNUZW5zb3I6IHRydWU7XG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBkYXRhIHR5cGUgb2YgdGhlIHRlbnNvci5cbiAgICAgKi9cbiAgICByZWFkb25seSB0eXBlOiBUZW5zb3IuVHlwZTtcbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHNoYXBlIG9mIHRoZSB0ZW5zb3IuXG4gICAgICpcbiAgICAgKiBJZiB0aGUgc2hhcGUgaXMgbm90IGRlZmluZWQsIHRoZSB2YWx1ZSB3aWxsIGFuIGVtcHR5IGFycmF5LiBPdGhlcndpc2UsIGl0IHdpbGwgYmUgYW4gYXJyYXkgcmVwcmVzZW50aW5nIHRoZSBzaGFwZVxuICAgICAqIG9mIHRoZSB0ZW5zb3IuIEVhY2ggZWxlbWVudCBpbiB0aGUgYXJyYXkgY2FuIGJlIGEgbnVtYmVyIG9yIGEgc3RyaW5nLiBJZiB0aGUgZWxlbWVudCBpcyBhIG51bWJlciwgaXQgcmVwcmVzZW50c1xuICAgICAqIHRoZSBjb3JyZXNwb25kaW5nIGRpbWVuc2lvbiBzaXplLiBJZiB0aGUgZWxlbWVudCBpcyBhIHN0cmluZywgaXQgcmVwcmVzZW50cyBhIHN5bWJvbGljIGRpbWVuc2lvbi5cbiAgICAgKi9cbiAgICByZWFkb25seSBzaGFwZTogUmVhZG9ubHlBcnJheTxudW1iZXIgfCBzdHJpbmc+O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudHMgdGhlIG1ldGFkYXRhIG9mIGEgdmFsdWUuXG4gICAqL1xuICBleHBvcnQgdHlwZSBWYWx1ZU1ldGFkYXRhID0gTm9uVGVuc29yVmFsdWVNZXRhZGF0YSB8IFRlbnNvclZhbHVlTWV0YWRhdGE7XG5cbiAgLy8gI2VuZHJlZ2lvblxufVxuXG4vKipcbiAqIFJlcHJlc2VudCBhIHJ1bnRpbWUgaW5zdGFuY2Ugb2YgYW4gT05OWCBtb2RlbC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbmZlcmVuY2VTZXNzaW9uIHtcbiAgLy8gI3JlZ2lvbiBydW4oKVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlIHRoZSBtb2RlbCBhc3luY2hyb25vdXNseSB3aXRoIHRoZSBnaXZlbiBmZWVkcyBhbmQgb3B0aW9ucy5cbiAgICpcbiAgICogQHBhcmFtIGZlZWRzIC0gUmVwcmVzZW50YXRpb24gb2YgdGhlIG1vZGVsIGlucHV0LiBTZWUgdHlwZSBkZXNjcmlwdGlvbiBvZiBgSW5mZXJlbmNlU2Vzc2lvbi5JbnB1dFR5cGVgIGZvciBkZXRhaWwuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gT3B0aW9uYWwuIEEgc2V0IG9mIG9wdGlvbnMgdGhhdCBjb250cm9scyB0aGUgYmVoYXZpb3Igb2YgbW9kZWwgaW5mZXJlbmNlLlxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIG1hcCwgd2hpY2ggdXNlcyBvdXRwdXQgbmFtZXMgYXMga2V5cyBhbmQgT25ueFZhbHVlIGFzIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICAgKi9cbiAgcnVuKGZlZWRzOiBJbmZlcmVuY2VTZXNzaW9uLkZlZWRzVHlwZSwgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uUnVuT3B0aW9ucyk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbi5SZXR1cm5UeXBlPjtcblxuICAvKipcbiAgICogRXhlY3V0ZSB0aGUgbW9kZWwgYXN5bmNocm9ub3VzbHkgd2l0aCB0aGUgZ2l2ZW4gZmVlZHMsIGZldGNoZXMgYW5kIG9wdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSBmZWVkcyAtIFJlcHJlc2VudGF0aW9uIG9mIHRoZSBtb2RlbCBpbnB1dC4gU2VlIHR5cGUgZGVzY3JpcHRpb24gb2YgYEluZmVyZW5jZVNlc3Npb24uSW5wdXRUeXBlYCBmb3IgZGV0YWlsLlxuICAgKiBAcGFyYW0gZmV0Y2hlcyAtIFJlcHJlc2VudGF0aW9uIG9mIHRoZSBtb2RlbCBvdXRwdXQuIFNlZSB0eXBlIGRlc2NyaXB0aW9uIG9mIGBJbmZlcmVuY2VTZXNzaW9uLk91dHB1dFR5cGVgIGZvclxuICAgKiBkZXRhaWwuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gT3B0aW9uYWwuIEEgc2V0IG9mIG9wdGlvbnMgdGhhdCBjb250cm9scyB0aGUgYmVoYXZpb3Igb2YgbW9kZWwgaW5mZXJlbmNlLlxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIG1hcCwgd2hpY2ggdXNlcyBvdXRwdXQgbmFtZXMgYXMga2V5cyBhbmQgT25ueFZhbHVlIGFzIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICAgKi9cbiAgcnVuKFxuICAgIGZlZWRzOiBJbmZlcmVuY2VTZXNzaW9uLkZlZWRzVHlwZSxcbiAgICBmZXRjaGVzOiBJbmZlcmVuY2VTZXNzaW9uLkZldGNoZXNUeXBlLFxuICAgIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMsXG4gICk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbi5SZXR1cm5UeXBlPjtcblxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiByZWxlYXNlKClcblxuICAvKipcbiAgICogUmVsZWFzZSB0aGUgaW5mZXJlbmNlIHNlc3Npb24gYW5kIHRoZSB1bmRlcmx5aW5nIHJlc291cmNlcy5cbiAgICovXG4gIHJlbGVhc2UoKTogUHJvbWlzZTx2b2lkPjtcblxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBwcm9maWxpbmdcblxuICAvKipcbiAgICogU3RhcnQgcHJvZmlsaW5nLlxuICAgKi9cbiAgc3RhcnRQcm9maWxpbmcoKTogdm9pZDtcblxuICAvKipcbiAgICogRW5kIHByb2ZpbGluZy5cbiAgICovXG4gIGVuZFByb2ZpbGluZygpOiB2b2lkO1xuXG4gIC8vICNlbmRyZWdpb25cblxuICAvLyAjcmVnaW9uIG1ldGFkYXRhXG5cbiAgLyoqXG4gICAqIEdldCBpbnB1dCBuYW1lcyBvZiB0aGUgbG9hZGVkIG1vZGVsLlxuICAgKi9cbiAgcmVhZG9ubHkgaW5wdXROYW1lczogcmVhZG9ubHkgc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEdldCBvdXRwdXQgbmFtZXMgb2YgdGhlIGxvYWRlZCBtb2RlbC5cbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dE5hbWVzOiByZWFkb25seSBzdHJpbmdbXTtcblxuICAvKipcbiAgICogR2V0IGlucHV0IG1ldGFkYXRhIG9mIHRoZSBsb2FkZWQgbW9kZWwuXG4gICAqL1xuICByZWFkb25seSBpbnB1dE1ldGFkYXRhOiByZWFkb25seSBJbmZlcmVuY2VTZXNzaW9uLlZhbHVlTWV0YWRhdGFbXTtcblxuICAvKipcbiAgICogR2V0IG91dHB1dCBtZXRhZGF0YSBvZiB0aGUgbG9hZGVkIG1vZGVsLlxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0TWV0YWRhdGE6IHJlYWRvbmx5IEluZmVyZW5jZVNlc3Npb24uVmFsdWVNZXRhZGF0YVtdO1xuXG4gIC8vICNlbmRyZWdpb25cbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbmZlcmVuY2VTZXNzaW9uRmFjdG9yeSB7XG4gIC8vICNyZWdpb24gY3JlYXRlKClcblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IGluZmVyZW5jZSBzZXNzaW9uIGFuZCBsb2FkIG1vZGVsIGFzeW5jaHJvbm91c2x5IGZyb20gYW4gT05OWCBtb2RlbCBmaWxlLlxuICAgKlxuICAgKiBAcGFyYW0gdXJpIC0gVGhlIFVSSSBvciBmaWxlIHBhdGggb2YgdGhlIG1vZGVsIHRvIGxvYWQuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gc3BlY2lmeSBjb25maWd1cmF0aW9uIGZvciBjcmVhdGluZyBhIG5ldyBpbmZlcmVuY2Ugc2Vzc2lvbi5cbiAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gSW5mZXJlbmNlU2Vzc2lvbiBvYmplY3QuXG4gICAqL1xuICBjcmVhdGUodXJpOiBzdHJpbmcsIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uPjtcblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IGluZmVyZW5jZSBzZXNzaW9uIGFuZCBsb2FkIG1vZGVsIGFzeW5jaHJvbm91c2x5IGZyb20gYW4gYXJyYXkgYnVmZXIuXG4gICAqXG4gICAqIEBwYXJhbSBidWZmZXIgLSBBbiBBcnJheUJ1ZmZlciByZXByZXNlbnRhdGlvbiBvZiBhbiBPTk5YIG1vZGVsLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIHNwZWNpZnkgY29uZmlndXJhdGlvbiBmb3IgY3JlYXRpbmcgYSBuZXcgaW5mZXJlbmNlIHNlc3Npb24uXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIEluZmVyZW5jZVNlc3Npb24gb2JqZWN0LlxuICAgKi9cbiAgY3JlYXRlKGJ1ZmZlcjogQXJyYXlCdWZmZXJMaWtlLCBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8SW5mZXJlbmNlU2Vzc2lvbj47XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBpbmZlcmVuY2Ugc2Vzc2lvbiBhbmQgbG9hZCBtb2RlbCBhc3luY2hyb25vdXNseSBmcm9tIHNlZ21lbnQgb2YgYW4gYXJyYXkgYnVmZXIuXG4gICAqXG4gICAqIEBwYXJhbSBidWZmZXIgLSBBbiBBcnJheUJ1ZmZlciByZXByZXNlbnRhdGlvbiBvZiBhbiBPTk5YIG1vZGVsLlxuICAgKiBAcGFyYW0gYnl0ZU9mZnNldCAtIFRoZSBiZWdpbm5pbmcgb2YgdGhlIHNwZWNpZmllZCBwb3J0aW9uIG9mIHRoZSBhcnJheSBidWZmZXIuXG4gICAqIEBwYXJhbSBieXRlTGVuZ3RoIC0gVGhlIGxlbmd0aCBpbiBieXRlcyBvZiB0aGUgYXJyYXkgYnVmZmVyLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIHNwZWNpZnkgY29uZmlndXJhdGlvbiBmb3IgY3JlYXRpbmcgYSBuZXcgaW5mZXJlbmNlIHNlc3Npb24uXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIEluZmVyZW5jZVNlc3Npb24gb2JqZWN0LlxuICAgKi9cbiAgY3JlYXRlKFxuICAgIGJ1ZmZlcjogQXJyYXlCdWZmZXJMaWtlLFxuICAgIGJ5dGVPZmZzZXQ6IG51bWJlcixcbiAgICBieXRlTGVuZ3RoPzogbnVtYmVyLFxuICAgIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zLFxuICApOiBQcm9taXNlPEluZmVyZW5jZVNlc3Npb24+O1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgaW5mZXJlbmNlIHNlc3Npb24gYW5kIGxvYWQgbW9kZWwgYXN5bmNocm9ub3VzbHkgZnJvbSBhIFVpbnQ4QXJyYXkuXG4gICAqXG4gICAqIEBwYXJhbSBidWZmZXIgLSBBIFVpbnQ4QXJyYXkgcmVwcmVzZW50YXRpb24gb2YgYW4gT05OWCBtb2RlbC5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBzcGVjaWZ5IGNvbmZpZ3VyYXRpb24gZm9yIGNyZWF0aW5nIGEgbmV3IGluZmVyZW5jZSBzZXNzaW9uLlxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBJbmZlcmVuY2VTZXNzaW9uIG9iamVjdC5cbiAgICovXG4gIGNyZWF0ZShidWZmZXI6IFVpbnQ4QXJyYXksIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uPjtcblxuICAvLyAjZW5kcmVnaW9uXG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cbmV4cG9ydCBjb25zdCBJbmZlcmVuY2VTZXNzaW9uOiBJbmZlcmVuY2VTZXNzaW9uRmFjdG9yeSA9IEluZmVyZW5jZVNlc3Npb25JbXBsO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBPcHRpb25zRm9ybWF0LCBPcHRpb25zTm9ybWFsaXphdGlvblBhcmFtZXRlcnMsIE9wdGlvbnNUZW5zb3JMYXlvdXQgfSBmcm9tICcuL3RlbnNvci1mYWN0b3J5LmpzJztcblxuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JUb0RhdGFVcmxPcHRpb25zIGV4dGVuZHMgT3B0aW9uc1RlbnNvckxheW91dCwgT3B0aW9uc0Zvcm1hdCwgT3B0aW9uc05vcm1hbGl6YXRpb25QYXJhbWV0ZXJzIHt9XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yVG9JbWFnZURhdGFPcHRpb25zIGV4dGVuZHMgT3B0aW9uc1RlbnNvckxheW91dCwgT3B0aW9uc0Zvcm1hdCwgT3B0aW9uc05vcm1hbGl6YXRpb25QYXJhbWV0ZXJzIHt9XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udmVyc2lvblV0aWxzIHtcbiAgLyoqXG4gICAqIGNyZWF0ZXMgYSBEYXRhVVJMIGluc3RhbmNlIGZyb20gdGVuc29yXG4gICAqXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gQW4gb3B0aW9uYWwgb2JqZWN0IHJlcHJlc2VudGluZyBvcHRpb25zIGZvciBjcmVhdGluZyBhIERhdGFVUkwgaW5zdGFuY2UgZnJvbSB0aGUgdGVuc29yLlxuICAgKlxuICAgKiBUaGUgZm9sbG93aW5nIGRlZmF1bHQgc2V0dGluZ3Mgd2lsbCBiZSBhcHBsaWVkOlxuICAgKiAtIGBmb3JtYXRgOiBgJ1JHQidgXG4gICAqIC0gYHRlbnNvckxheW91dGA6IGAnTkNIVydgXG4gICAqIEByZXR1cm5zIGEgRGF0YVVSTCBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBpbWFnZSBjb252ZXJ0ZWQgZnJvbSB0ZW5zb3IgZGF0YVxuICAgKi9cbiAgdG9EYXRhVVJMKG9wdGlvbnM/OiBUZW5zb3JUb0RhdGFVcmxPcHRpb25zKTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBjcmVhdGVzIGFuIEltYWdlRGF0YSBpbnN0YW5jZSBmcm9tIHRlbnNvclxuICAgKlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFuIG9wdGlvbmFsIG9iamVjdCByZXByZXNlbnRpbmcgb3B0aW9ucyBmb3IgY3JlYXRpbmcgYW4gSW1hZ2VEYXRhIGluc3RhbmNlIGZyb20gdGhlIHRlbnNvci5cbiAgICpcbiAgICogVGhlIGZvbGxvd2luZyBkZWZhdWx0IHNldHRpbmdzIHdpbGwgYmUgYXBwbGllZDpcbiAgICogLSBgZm9ybWF0YDogYCdSR0InYFxuICAgKiAtIGB0ZW5zb3JMYXlvdXRgOiBgJ05DSFcnYFxuICAgKiBAcmV0dXJucyBhbiBJbWFnZURhdGEgaW5zdGFuY2UgcmVwcmVzZW50aW5nIHRoZSBpbWFnZSBjb252ZXJ0ZWQgZnJvbSB0ZW5zb3IgZGF0YVxuICAgKi9cbiAgdG9JbWFnZURhdGEob3B0aW9ucz86IFRlbnNvclRvSW1hZ2VEYXRhT3B0aW9ucyk6IEltYWdlRGF0YTtcbn1cbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yLCBUeXBlZFRlbnNvciB9IGZyb20gJy4vdGVuc29yLmpzJztcblxuZXhwb3J0IHR5cGUgSW1hZ2VGb3JtYXQgPSAnUkdCJyB8ICdSR0JBJyB8ICdCR1InIHwgJ1JCRyc7XG5leHBvcnQgdHlwZSBJbWFnZVRlbnNvckxheW91dCA9ICdOSFdDJyB8ICdOQ0hXJztcblxuLy8gdGhlIGZvbGxvd2luZyByZWdpb24gY29udGFpbnMgdHlwZSBkZWZpbml0aW9ucyBmb3IgY29uc3RydWN0aW5nIHRlbnNvciBmcm9tIGEgc3BlY2lmaWMgbG9jYXRpb24uXG5cbi8vICNyZWdpb24gdHlwZXMgZm9yIGNvbnN0cnVjdGluZyBhIHRlbnNvciBmcm9tIGEgc3BlY2lmaWMgbG9jYXRpb25cblxuLyoqXG4gKiByZXByZXNlbnQgY29tbW9uIHByb3BlcnRpZXMgb2YgdGhlIHBhcmFtZXRlciBmb3IgY29uc3RydWN0aW5nIGEgdGVuc29yIGZyb20gYSBzcGVjaWZpYyBsb2NhdGlvbi5cbiAqL1xuaW50ZXJmYWNlIENvbW1vbkNvbnN0cnVjdG9yUGFyYW1ldGVyczxUPiBleHRlbmRzIFBpY2s8VGVuc29yLCAnZGltcyc+IHtcbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIGRhdGEgdHlwZSBvZiB0aGUgdGVuc29yLlxuICAgKi9cbiAgcmVhZG9ubHkgdHlwZTogVDtcbn1cblxuLyoqXG4gKiByZXByZXNlbnQgdGhlIHBhcmFtZXRlciBmb3IgY29uc3RydWN0aW5nIGEgdGVuc29yIGZyb20gYSBHUFUgcmVzb3VyY2UuXG4gKi9cbmludGVyZmFjZSBHcHVSZXNvdXJjZUNvbnN0cnVjdG9yUGFyYW1ldGVyczxUIGV4dGVuZHMgVGVuc29yLlR5cGU+IHtcbiAgLyoqXG4gICAqIGFuIG9wdGlvbmFsIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGRvd25sb2FkIGRhdGEgZnJvbSBHUFUgdG8gQ1BVLlxuICAgKlxuICAgKiBJZiBub3QgcHJvdmlkZWQsIHRoZSB0ZW5zb3IgdHJlYXQgdGhlIEdQVSBkYXRhIGFzIGV4dGVybmFsIHJlc291cmNlLlxuICAgKi9cbiAgZG93bmxvYWQ/KCk6IFByb21pc2U8VGVuc29yLkRhdGFUeXBlTWFwW1RdPjtcblxuICAvKipcbiAgICogYW4gb3B0aW9uYWwgY2FsbGJhY2sgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGNhbGxlZCB3aGVuIHRoZSB0ZW5zb3IgaXMgZGlzcG9zZWQuXG4gICAqXG4gICAqIElmIG5vdCBwcm92aWRlZCwgdGhlIHRlbnNvciB0cmVhdCB0aGUgR1BVIGRhdGEgYXMgZXh0ZXJuYWwgcmVzb3VyY2UuXG4gICAqL1xuICBkaXNwb3NlPygpOiB2b2lkO1xufVxuXG4vKipcbiAqIHJlcHJlc2VudCB0aGUgcGFyYW1ldGVyIGZvciBjb25zdHJ1Y3RpbmcgYSB0ZW5zb3IgZnJvbSBhIHBpbm5lZCBDUFUgYnVmZmVyXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ3B1UGlubmVkQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQgZXh0ZW5kcyBUZW5zb3IuQ3B1UGlubmVkRGF0YVR5cGVzID0gVGVuc29yLkNwdVBpbm5lZERhdGFUeXBlcz5cbiAgZXh0ZW5kcyBDb21tb25Db25zdHJ1Y3RvclBhcmFtZXRlcnM8VD4ge1xuICAvKipcbiAgICogU3BlY2lmeSB0aGUgbG9jYXRpb24gb2YgdGhlIGRhdGEgdG8gYmUgJ2NwdS1waW5uZWQnLlxuICAgKi9cbiAgcmVhZG9ubHkgbG9jYXRpb246ICdjcHUtcGlubmVkJztcbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIENQVSBwaW5uZWQgYnVmZmVyIHRoYXQgaG9sZHMgdGhlIHRlbnNvciBkYXRhLlxuICAgKi9cbiAgcmVhZG9ubHkgZGF0YTogVGVuc29yLkRhdGFUeXBlTWFwW1RdO1xufVxuXG4vKipcbiAqIHJlcHJlc2VudCB0aGUgcGFyYW1ldGVyIGZvciBjb25zdHJ1Y3RpbmcgYSB0ZW5zb3IgZnJvbSBhIFdlYkdMIHRleHR1cmVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZXh0dXJlQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQgZXh0ZW5kcyBUZW5zb3IuVGV4dHVyZURhdGFUeXBlcyA9IFRlbnNvci5UZXh0dXJlRGF0YVR5cGVzPlxuICBleHRlbmRzIENvbW1vbkNvbnN0cnVjdG9yUGFyYW1ldGVyczxUPixcbiAgICBHcHVSZXNvdXJjZUNvbnN0cnVjdG9yUGFyYW1ldGVyczxUPiB7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoZSBsb2NhdGlvbiBvZiB0aGUgZGF0YSB0byBiZSAndGV4dHVyZScuXG4gICAqL1xuICByZWFkb25seSBsb2NhdGlvbjogJ3RleHR1cmUnO1xuICAvKipcbiAgICogU3BlY2lmeSB0aGUgV2ViR0wgdGV4dHVyZSB0aGF0IGhvbGRzIHRoZSB0ZW5zb3IgZGF0YS5cbiAgICovXG4gIHJlYWRvbmx5IHRleHR1cmU6IFRlbnNvci5UZXh0dXJlVHlwZTtcbn1cblxuLyoqXG4gKiByZXByZXNlbnQgdGhlIHBhcmFtZXRlciBmb3IgY29uc3RydWN0aW5nIGEgdGVuc29yIGZyb20gYSBXZWJHUFUgYnVmZmVyXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR3B1QnVmZmVyQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQgZXh0ZW5kcyBUZW5zb3IuR3B1QnVmZmVyRGF0YVR5cGVzID0gVGVuc29yLkdwdUJ1ZmZlckRhdGFUeXBlcz5cbiAgZXh0ZW5kcyBDb21tb25Db25zdHJ1Y3RvclBhcmFtZXRlcnM8VD4sXG4gICAgR3B1UmVzb3VyY2VDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VD4ge1xuICAvKipcbiAgICogU3BlY2lmeSB0aGUgbG9jYXRpb24gb2YgdGhlIGRhdGEgdG8gYmUgJ2dwdS1idWZmZXInLlxuICAgKi9cbiAgcmVhZG9ubHkgbG9jYXRpb246ICdncHUtYnVmZmVyJztcbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIFdlYkdQVSBidWZmZXIgdGhhdCBob2xkcyB0aGUgdGVuc29yIGRhdGEuXG4gICAqL1xuICByZWFkb25seSBncHVCdWZmZXI6IFRlbnNvci5HcHVCdWZmZXJUeXBlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1MVGVuc29yQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQgZXh0ZW5kcyBUZW5zb3IuTUxUZW5zb3JEYXRhVHlwZXMgPSBUZW5zb3IuTUxUZW5zb3JEYXRhVHlwZXM+XG4gIGV4dGVuZHMgQ29tbW9uQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQ+LFxuICAgIEdwdVJlc291cmNlQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQ+IHtcbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIGxvY2F0aW9uIG9mIHRoZSBkYXRhIHRvIGJlICdtbC10ZW5zb3InLlxuICAgKi9cbiAgcmVhZG9ubHkgbG9jYXRpb246ICdtbC10ZW5zb3InO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoZSBXZWJOTiBNTFRlbnNvciB0aGF0IGhvbGRzIHRoZSB0ZW5zb3IgZGF0YS5cbiAgICovXG4gIHJlYWRvbmx5IG1sVGVuc29yOiBUZW5zb3IuTUxUZW5zb3JUeXBlO1xufVxuXG4vLyAjZW5kcmVnaW9uXG5cbi8vIHRoZSBmb2xsb3dpbmcgcmVnaW9uIGNvbnRhaW5zIHR5cGUgZGVmaW5pdGlvbnMgb2YgZWFjaCBpbmRpdmlkdWFsIG9wdGlvbnMuXG4vLyB0aGUgdGVuc29yIGZhY3RvcnkgZnVuY3Rpb25zIHVzZSBhIGNvbXBvc2l0aW9uIG9mIHRob3NlIG9wdGlvbnMgYXMgdGhlIHBhcmFtZXRlciB0eXBlLlxuXG4vLyAjcmVnaW9uIE9wdGlvbnMgZmllbGRzXG5cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uc0Zvcm1hdCB7XG4gIC8qKlxuICAgKiBEZXNjcmliZXMgdGhlIGltYWdlIGZvcm1hdCByZXByZXNlbnRlZCBpbiBSR0JBIGNvbG9yIHNwYWNlLlxuICAgKi9cbiAgZm9ybWF0PzogSW1hZ2VGb3JtYXQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uc1RlbnNvckZvcm1hdCB7XG4gIC8qKlxuICAgKiBEZXNjcmliZXMgdGhlIGltYWdlIGZvcm1hdCBvZiB0aGUgdGVuc29yLlxuICAgKlxuICAgKiBOT1RFOiB0aGlzIGlzIGRpZmZlcmVudCBmcm9tIG9wdGlvbiAnZm9ybWF0Jy4gV2hpbGUgb3B0aW9uICdmb3JtYXQnIHJlcHJlc2VudHMgdGhlIG9yaWdpbmFsIGltYWdlLCAndGVuc29yRm9ybWF0J1xuICAgKiByZXByZXNlbnRzIHRoZSB0YXJnZXQgZm9ybWF0IG9mIHRoZSB0ZW5zb3IuIEEgdHJhbnNwb3NlIHdpbGwgYmUgcGVyZm9ybWVkIGlmIHRoZXkgYXJlIGRpZmZlcmVudC5cbiAgICovXG4gIHRlbnNvckZvcm1hdD86IEltYWdlRm9ybWF0O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE9wdGlvbnNUZW5zb3JEYXRhVHlwZSB7XG4gIC8qKlxuICAgKiBEZXNjcmliZXMgdGhlIGRhdGEgdHlwZSBvZiB0aGUgdGVuc29yLlxuICAgKi9cbiAgZGF0YVR5cGU/OiAnZmxvYXQzMicgfCAndWludDgnO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE9wdGlvbnNUZW5zb3JMYXlvdXQge1xuICAvKipcbiAgICogRGVzY3JpYmVzIHRoZSB0ZW5zb3IgbGF5b3V0IHdoZW4gcmVwcmVzZW50aW5nIGRhdGEgb2Ygb25lIG9yIG1vcmUgaW1hZ2UocykuXG4gICAqL1xuICB0ZW5zb3JMYXlvdXQ/OiBJbWFnZVRlbnNvckxheW91dDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcHRpb25zRGltZW5zaW9ucyB7XG4gIC8qKlxuICAgKiBEZXNjcmliZXMgdGhlIGltYWdlIGhlaWdodCBpbiBwaXhlbFxuICAgKi9cbiAgaGVpZ2h0PzogbnVtYmVyO1xuICAvKipcbiAgICogRGVzY3JpYmVzIHRoZSBpbWFnZSB3aWR0aCBpbiBwaXhlbFxuICAgKi9cbiAgd2lkdGg/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uUmVzaXplZERpbWVuc2lvbnMge1xuICAvKipcbiAgICogRGVzY3JpYmVzIHRoZSByZXNpemVkIGhlaWdodC4gSWYgb21pdHRlZCwgb3JpZ2luYWwgaGVpZ2h0IHdpbGwgYmUgdXNlZC5cbiAgICovXG4gIHJlc2l6ZWRIZWlnaHQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBEZXNjcmliZXMgcmVzaXplZCB3aWR0aCAtIGNhbiBiZSBhY2Nlc3NlZCB2aWEgdGVuc29yIGRpbWVuc2lvbnMgYXMgd2VsbFxuICAgKi9cbiAgcmVzaXplZFdpZHRoPzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE9wdGlvbnNOb3JtYWxpemF0aW9uUGFyYW1ldGVycyB7XG4gIC8qKlxuICAgKiBEZXNjcmliZXMgbm9ybWFsaXphdGlvbiBwYXJhbWV0ZXJzIHdoZW4gcHJlcHJvY2Vzc2luZyB0aGUgaW1hZ2UgYXMgbW9kZWwgaW5wdXQuXG4gICAqXG4gICAqIERhdGEgZWxlbWVudCBhcmUgcmFuZ2VkIGZyb20gMCB0byAyNTUuXG4gICAqL1xuICBub3JtPzoge1xuICAgIC8qKlxuICAgICAqIFRoZSAnYmlhcycgdmFsdWUgZm9yIGltYWdlIG5vcm1hbGl6YXRpb24uXG4gICAgICogLSBJZiBvbWl0dGVkLCB1c2UgZGVmYXVsdCB2YWx1ZSAwLlxuICAgICAqIC0gSWYgaXQncyBhIHNpbmdsZSBudW1iZXIsIGFwcGx5IHRvIGVhY2ggY2hhbm5lbFxuICAgICAqIC0gSWYgaXQncyBhbiBhcnJheSBvZiAzIG9yIDQgbnVtYmVycywgYXBwbHkgZWxlbWVudC13aXNlLiBOdW1iZXIgb2YgZWxlbWVudHMgbmVlZCB0byBtYXRjaCB0aGUgbnVtYmVyIG9mIGNoYW5uZWxzXG4gICAgICogZm9yIHRoZSBjb3JyZXNwb25kaW5nIGltYWdlIGZvcm1hdFxuICAgICAqL1xuICAgIGJpYXM/OiBudW1iZXIgfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgICAvKipcbiAgICAgKiBUaGUgJ21lYW4nIHZhbHVlIGZvciBpbWFnZSBub3JtYWxpemF0aW9uLlxuICAgICAqIC0gSWYgb21pdHRlZCwgdXNlIGRlZmF1bHQgdmFsdWUgMjU1LlxuICAgICAqIC0gSWYgaXQncyBhIHNpbmdsZSBudW1iZXIsIGFwcGx5IHRvIGVhY2ggY2hhbm5lbFxuICAgICAqIC0gSWYgaXQncyBhbiBhcnJheSBvZiAzIG9yIDQgbnVtYmVycywgYXBwbHkgZWxlbWVudC13aXNlLiBOdW1iZXIgb2YgZWxlbWVudHMgbmVlZCB0byBtYXRjaCB0aGUgbnVtYmVyIG9mIGNoYW5uZWxzXG4gICAgICogZm9yIHRoZSBjb3JyZXNwb25kaW5nIGltYWdlIGZvcm1hdFxuICAgICAqL1xuICAgIG1lYW4/OiBudW1iZXIgfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgfTtcbn1cblxuLy8gI2VuZHJlZ2lvblxuXG4vLyAjcmVnaW9uIE9wdGlvbnMgY29tcG9zaXRpb25cblxuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JGcm9tSW1hZ2VEYXRhT3B0aW9uc1xuICBleHRlbmRzIE9wdGlvblJlc2l6ZWREaW1lbnNpb25zLFxuICAgIE9wdGlvbnNUZW5zb3JGb3JtYXQsXG4gICAgT3B0aW9uc1RlbnNvckxheW91dCxcbiAgICBPcHRpb25zVGVuc29yRGF0YVR5cGUsXG4gICAgT3B0aW9uc05vcm1hbGl6YXRpb25QYXJhbWV0ZXJzIHt9XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yRnJvbUltYWdlRWxlbWVudE9wdGlvbnNcbiAgZXh0ZW5kcyBPcHRpb25SZXNpemVkRGltZW5zaW9ucyxcbiAgICBPcHRpb25zVGVuc29yRm9ybWF0LFxuICAgIE9wdGlvbnNUZW5zb3JMYXlvdXQsXG4gICAgT3B0aW9uc1RlbnNvckRhdGFUeXBlLFxuICAgIE9wdGlvbnNOb3JtYWxpemF0aW9uUGFyYW1ldGVycyB7fVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvckZyb21VcmxPcHRpb25zXG4gIGV4dGVuZHMgT3B0aW9uc0RpbWVuc2lvbnMsXG4gICAgT3B0aW9uUmVzaXplZERpbWVuc2lvbnMsXG4gICAgT3B0aW9uc1RlbnNvckZvcm1hdCxcbiAgICBPcHRpb25zVGVuc29yTGF5b3V0LFxuICAgIE9wdGlvbnNUZW5zb3JEYXRhVHlwZSxcbiAgICBPcHRpb25zTm9ybWFsaXphdGlvblBhcmFtZXRlcnMge31cblxuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JGcm9tSW1hZ2VCaXRtYXBPcHRpb25zXG4gIGV4dGVuZHMgT3B0aW9uUmVzaXplZERpbWVuc2lvbnMsXG4gICAgT3B0aW9uc1RlbnNvckZvcm1hdCxcbiAgICBPcHRpb25zVGVuc29yTGF5b3V0LFxuICAgIE9wdGlvbnNUZW5zb3JEYXRhVHlwZSxcbiAgICBPcHRpb25zTm9ybWFsaXphdGlvblBhcmFtZXRlcnMge31cblxuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JGcm9tVGV4dHVyZU9wdGlvbnM8VCBleHRlbmRzIFRlbnNvci5UZXh0dXJlRGF0YVR5cGVzPlxuICBleHRlbmRzIFJlcXVpcmVkPE9wdGlvbnNEaW1lbnNpb25zPixcbiAgICBPcHRpb25zRm9ybWF0LFxuICAgIEdwdVJlc291cmNlQ29uc3RydWN0b3JQYXJhbWV0ZXJzPFQ+IC8qIFRPRE86IGFkZCBtb3JlICovIHt9XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGVuc29yRnJvbUdwdUJ1ZmZlck9wdGlvbnM8VCBleHRlbmRzIFRlbnNvci5HcHVCdWZmZXJEYXRhVHlwZXM+XG4gIGV4dGVuZHMgUGljazxUZW5zb3IsICdkaW1zJz4sXG4gICAgR3B1UmVzb3VyY2VDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VD4ge1xuICAvKipcbiAgICogRGVzY3JpYmVzIHRoZSBkYXRhIHR5cGUgb2YgdGhlIHRlbnNvci5cbiAgICovXG4gIGRhdGFUeXBlPzogVDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JGcm9tTUxUZW5zb3JPcHRpb25zPFQgZXh0ZW5kcyBUZW5zb3IuTUxUZW5zb3JEYXRhVHlwZXM+XG4gIGV4dGVuZHMgUGljazxUZW5zb3IsICdkaW1zJz4sXG4gICAgR3B1UmVzb3VyY2VDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VD4ge1xuICAvKipcbiAgICogRGVzY3JpYmVzIHRoZSBkYXRhIHR5cGUgb2YgdGhlIHRlbnNvci5cbiAgICovXG4gIGRhdGFUeXBlPzogVDtcbn1cblxuLy8gI2VuZHJlZ2lvblxuXG4vKipcbiAqIHR5cGUgVGVuc29yRmFjdG9yeSBkZWZpbmVzIHRoZSBmYWN0b3J5IGZ1bmN0aW9ucyBvZiAnVGVuc29yJyB0byBjcmVhdGUgdGVuc29yIGluc3RhbmNlcyBmcm9tIGV4aXN0aW5nIGRhdGEgb3JcbiAqIHJlc291cmNlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JGYWN0b3J5IHtcbiAgLyoqXG4gICAqIGNyZWF0ZSBhIHRlbnNvciBmcm9tIGFuIEltYWdlRGF0YSBvYmplY3RcbiAgICpcbiAgICogQHBhcmFtIGltYWdlRGF0YSAtIHRoZSBJbWFnZURhdGEgb2JqZWN0IHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFuIG9wdGlvbmFsIG9iamVjdCByZXByZXNlbnRpbmcgb3B0aW9ucyBmb3IgY3JlYXRpbmcgdGVuc29yIGZyb20gSW1hZ2VEYXRhLlxuICAgKlxuICAgKiBUaGUgZm9sbG93aW5nIGRlZmF1bHQgc2V0dGluZ3Mgd2lsbCBiZSBhcHBsaWVkOlxuICAgKiAtIGB0ZW5zb3JGb3JtYXRgOiBgJ1JHQidgXG4gICAqIC0gYHRlbnNvckxheW91dGA6IGAnTkNIVydgXG4gICAqIC0gYGRhdGFUeXBlYDogYCdmbG9hdDMyJ2BcbiAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSB0ZW5zb3Igb2JqZWN0XG4gICAqL1xuICBmcm9tSW1hZ2UoXG4gICAgaW1hZ2VEYXRhOiBJbWFnZURhdGEsXG4gICAgb3B0aW9ucz86IFRlbnNvckZyb21JbWFnZURhdGFPcHRpb25zLFxuICApOiBQcm9taXNlPFR5cGVkVGVuc29yPCdmbG9hdDMyJz4gfCBUeXBlZFRlbnNvcjwndWludDgnPj47XG5cbiAgLyoqXG4gICAqIGNyZWF0ZSBhIHRlbnNvciBmcm9tIGEgSFRNTEltYWdlRWxlbWVudCBvYmplY3RcbiAgICpcbiAgICogQHBhcmFtIGltYWdlRWxlbWVudCAtIHRoZSBIVE1MSW1hZ2VFbGVtZW50IG9iamVjdCB0byBjcmVhdGUgdGVuc29yIGZyb21cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBBbiBvcHRpb25hbCBvYmplY3QgcmVwcmVzZW50aW5nIG9wdGlvbnMgZm9yIGNyZWF0aW5nIHRlbnNvciBmcm9tIEhUTUxJbWFnZUVsZW1lbnQuXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgZGVmYXVsdCBzZXR0aW5ncyB3aWxsIGJlIGFwcGxpZWQ6XG4gICAqIC0gYHRlbnNvckZvcm1hdGA6IGAnUkdCJ2BcbiAgICogLSBgdGVuc29yTGF5b3V0YDogYCdOQ0hXJ2BcbiAgICogLSBgZGF0YVR5cGVgOiBgJ2Zsb2F0MzInYFxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIHRlbnNvciBvYmplY3RcbiAgICovXG4gIGZyb21JbWFnZShcbiAgICBpbWFnZUVsZW1lbnQ6IEhUTUxJbWFnZUVsZW1lbnQsXG4gICAgb3B0aW9ucz86IFRlbnNvckZyb21JbWFnZUVsZW1lbnRPcHRpb25zLFxuICApOiBQcm9taXNlPFR5cGVkVGVuc29yPCdmbG9hdDMyJz4gfCBUeXBlZFRlbnNvcjwndWludDgnPj47XG5cbiAgLyoqXG4gICAqIGNyZWF0ZSBhIHRlbnNvciBmcm9tIFVSTFxuICAgKlxuICAgKiBAcGFyYW0gdXJsU291cmNlIC0gYSBzdHJpbmcgYXMgYSBVUkwgdG8gdGhlIGltYWdlIG9yIGEgZGF0YSBVUkwgY29udGFpbmluZyB0aGUgaW1hZ2UgZGF0YS5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBBbiBvcHRpb25hbCBvYmplY3QgcmVwcmVzZW50aW5nIG9wdGlvbnMgZm9yIGNyZWF0aW5nIHRlbnNvciBmcm9tIFVSTC5cbiAgICpcbiAgICogVGhlIGZvbGxvd2luZyBkZWZhdWx0IHNldHRpbmdzIHdpbGwgYmUgYXBwbGllZDpcbiAgICogLSBgdGVuc29yRm9ybWF0YDogYCdSR0InYFxuICAgKiAtIGB0ZW5zb3JMYXlvdXRgOiBgJ05DSFcnYFxuICAgKiAtIGBkYXRhVHlwZWA6IGAnZmxvYXQzMidgXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgdGVuc29yIG9iamVjdFxuICAgKi9cbiAgZnJvbUltYWdlKHVybFNvdXJjZTogc3RyaW5nLCBvcHRpb25zPzogVGVuc29yRnJvbVVybE9wdGlvbnMpOiBQcm9taXNlPFR5cGVkVGVuc29yPCdmbG9hdDMyJz4gfCBUeXBlZFRlbnNvcjwndWludDgnPj47XG5cbiAgLyoqXG4gICAqIGNyZWF0ZSBhIHRlbnNvciBmcm9tIGFuIEltYWdlQml0bWFwIG9iamVjdFxuICAgKlxuICAgKiBAcGFyYW0gYml0bWFwIC0gdGhlIEltYWdlQml0bWFwIG9iamVjdCB0byBjcmVhdGUgdGVuc29yIGZyb21cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBBbiBvcHRpb25hbCBvYmplY3QgcmVwcmVzZW50aW5nIG9wdGlvbnMgZm9yIGNyZWF0aW5nIHRlbnNvciBmcm9tIFVSTC5cbiAgICpcbiAgICogVGhlIGZvbGxvd2luZyBkZWZhdWx0IHNldHRpbmdzIHdpbGwgYmUgYXBwbGllZDpcbiAgICogLSBgdGVuc29yRm9ybWF0YDogYCdSR0InYFxuICAgKiAtIGB0ZW5zb3JMYXlvdXRgOiBgJ05DSFcnYFxuICAgKiAtIGBkYXRhVHlwZWA6IGAnZmxvYXQzMidgXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgdGVuc29yIG9iamVjdFxuICAgKi9cbiAgZnJvbUltYWdlKFxuICAgIGJpdG1hcDogSW1hZ2VCaXRtYXAsXG4gICAgb3B0aW9uczogVGVuc29yRnJvbUltYWdlQml0bWFwT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxUeXBlZFRlbnNvcjwnZmxvYXQzMic+IHwgVHlwZWRUZW5zb3I8J3VpbnQ4Jz4+O1xuXG4gIC8qKlxuICAgKiBjcmVhdGUgYSB0ZW5zb3IgZnJvbSBhIFdlYkdMIHRleHR1cmVcbiAgICpcbiAgICogQHBhcmFtIHRleHR1cmUgLSB0aGUgV2ViR0xUZXh0dXJlIG9iamVjdCB0byBjcmVhdGUgdGVuc29yIGZyb21cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBBbiBvcHRpb25hbCBvYmplY3QgcmVwcmVzZW50aW5nIG9wdGlvbnMgZm9yIGNyZWF0aW5nIHRlbnNvciBmcm9tIFdlYkdMIHRleHR1cmUuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGluY2x1ZGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gICAqIC0gYHdpZHRoYDogdGhlIHdpZHRoIG9mIHRoZSB0ZXh0dXJlLiBSZXF1aXJlZC5cbiAgICogLSBgaGVpZ2h0YDogdGhlIGhlaWdodCBvZiB0aGUgdGV4dHVyZS4gUmVxdWlyZWQuXG4gICAqIC0gYGZvcm1hdGA6IHRoZSBmb3JtYXQgb2YgdGhlIHRleHR1cmUuIElmIG9taXR0ZWQsIGFzc3VtZSAnUkdCQScuXG4gICAqIC0gYGRvd25sb2FkYDogYW4gb3B0aW9uYWwgZnVuY3Rpb24gdG8gZG93bmxvYWQgdGhlIHRlbnNvciBkYXRhIGZyb20gR1BVIHRvIENQVS4gSWYgb21pdHRlZCwgdGhlIEdQVSBkYXRhXG4gICAqIHdpbGwgbm90IGJlIGFibGUgdG8gZG93bmxvYWQuIFVzdWFsbHksIHRoaXMgaXMgcHJvdmlkZWQgYnkgYSBHUFUgYmFja2VuZCBmb3IgdGhlIGluZmVyZW5jZSBvdXRwdXRzLiBVc2VycyBkb24ndFxuICAgKiBuZWVkIHRvIHByb3ZpZGUgdGhpcyBmdW5jdGlvbi5cbiAgICogLSBgZGlzcG9zZWA6IGFuIG9wdGlvbmFsIGZ1bmN0aW9uIHRvIGRpc3Bvc2UgdGhlIHRlbnNvciBkYXRhIG9uIEdQVS4gSWYgb21pdHRlZCwgdGhlIEdQVSBkYXRhIHdpbGwgbm90IGJlIGRpc3Bvc2VkLlxuICAgKiBVc3VhbGx5LCB0aGlzIGlzIHByb3ZpZGVkIGJ5IGEgR1BVIGJhY2tlbmQgZm9yIHRoZSBpbmZlcmVuY2Ugb3V0cHV0cy4gVXNlcnMgZG9uJ3QgbmVlZCB0byBwcm92aWRlIHRoaXMgZnVuY3Rpb24uXG4gICAqXG4gICAqIEByZXR1cm5zIGEgdGVuc29yIG9iamVjdFxuICAgKi9cbiAgZnJvbVRleHR1cmU8VCBleHRlbmRzIFRlbnNvci5UZXh0dXJlRGF0YVR5cGVzID0gJ2Zsb2F0MzInPihcbiAgICB0ZXh0dXJlOiBUZW5zb3IuVGV4dHVyZVR5cGUsXG4gICAgb3B0aW9uczogVGVuc29yRnJvbVRleHR1cmVPcHRpb25zPFQ+LFxuICApOiBUeXBlZFRlbnNvcjwnZmxvYXQzMic+O1xuXG4gIC8qKlxuICAgKiBjcmVhdGUgYSB0ZW5zb3IgZnJvbSBhIFdlYkdQVSBidWZmZXJcbiAgICpcbiAgICogQHBhcmFtIGJ1ZmZlciAtIHRoZSBHUFVCdWZmZXIgb2JqZWN0IHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFuIG9wdGlvbmFsIG9iamVjdCByZXByZXNlbnRpbmcgb3B0aW9ucyBmb3IgY3JlYXRpbmcgdGVuc29yIGZyb20gV2ViR1BVIGJ1ZmZlci5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgaW5jbHVkZSBmb2xsb3dpbmcgcHJvcGVydGllczpcbiAgICogLSBgZGF0YVR5cGVgOiB0aGUgZGF0YSB0eXBlIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGFzc3VtZSAnZmxvYXQzMicuXG4gICAqIC0gYGRpbXNgOiB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIFJlcXVpcmVkLlxuICAgKiAtIGBkb3dubG9hZGA6IGFuIG9wdGlvbmFsIGZ1bmN0aW9uIHRvIGRvd25sb2FkIHRoZSB0ZW5zb3IgZGF0YSBmcm9tIEdQVSB0byBDUFUuIElmIG9taXR0ZWQsIHRoZSBHUFUgZGF0YVxuICAgKiB3aWxsIG5vdCBiZSBhYmxlIHRvIGRvd25sb2FkLiBVc3VhbGx5LCB0aGlzIGlzIHByb3ZpZGVkIGJ5IGEgR1BVIGJhY2tlbmQgZm9yIHRoZSBpbmZlcmVuY2Ugb3V0cHV0cy4gVXNlcnMgZG9uJ3RcbiAgICogbmVlZCB0byBwcm92aWRlIHRoaXMgZnVuY3Rpb24uXG4gICAqIC0gYGRpc3Bvc2VgOiBhbiBvcHRpb25hbCBmdW5jdGlvbiB0byBkaXNwb3NlIHRoZSB0ZW5zb3IgZGF0YSBvbiBHUFUuIElmIG9taXR0ZWQsIHRoZSBHUFUgZGF0YSB3aWxsIG5vdCBiZSBkaXNwb3NlZC5cbiAgICogVXN1YWxseSwgdGhpcyBpcyBwcm92aWRlZCBieSBhIEdQVSBiYWNrZW5kIGZvciB0aGUgaW5mZXJlbmNlIG91dHB1dHMuIFVzZXJzIGRvbid0IG5lZWQgdG8gcHJvdmlkZSB0aGlzIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAcmV0dXJucyBhIHRlbnNvciBvYmplY3RcbiAgICovXG4gIGZyb21HcHVCdWZmZXI8VCBleHRlbmRzIFRlbnNvci5HcHVCdWZmZXJEYXRhVHlwZXM+KFxuICAgIGJ1ZmZlcjogVGVuc29yLkdwdUJ1ZmZlclR5cGUsXG4gICAgb3B0aW9uczogVGVuc29yRnJvbUdwdUJ1ZmZlck9wdGlvbnM8VD4sXG4gICk6IFR5cGVkVGVuc29yPFQ+O1xuXG4gIC8qKlxuICAgKiBjcmVhdGUgYSB0ZW5zb3IgZnJvbSBhIFdlYk5OIE1MVGVuc29yXG4gICAqXG4gICAqIEBwYXJhbSB0ZW5zb3IgLSB0aGUgTUxUZW5zb3Igb2JqZWN0IHRvIGNyZWF0ZSB0ZW5zb3IgZnJvbVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFuIG9wdGlvbmFsIG9iamVjdCByZXByZXNlbnRpbmcgb3B0aW9ucyBmb3IgY3JlYXRpbmcgdGVuc29yIGZyb20gYSBXZWJOTiBNTFRlbnNvci5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgaW5jbHVkZSBmb2xsb3dpbmcgcHJvcGVydGllczpcbiAgICogLSBgZGF0YVR5cGVgOiB0aGUgZGF0YSB0eXBlIG9mIHRoZSB0ZW5zb3IuIElmIG9taXR0ZWQsIGFzc3VtZSAnZmxvYXQzMicuXG4gICAqIC0gYGRpbXNgOiB0aGUgZGltZW5zaW9uIG9mIHRoZSB0ZW5zb3IuIFJlcXVpcmVkLlxuICAgKiAtIGBkb3dubG9hZGA6IGFuIG9wdGlvbmFsIGZ1bmN0aW9uIHRvIGRvd25sb2FkIHRoZSB0ZW5zb3IgZGF0YSBmcm9tIHRoZSBNTFRlbnNvciB0byBDUFUuIElmIG9taXR0ZWQsIHRoZSBNTFRlbnNvclxuICAgKiBkYXRhIHdpbGwgbm90IGJlIGFibGUgdG8gZG93bmxvYWQuIFVzdWFsbHksIHRoaXMgaXMgcHJvdmlkZWQgYnkgdGhlIFdlYk5OIGJhY2tlbmQgZm9yIHRoZSBpbmZlcmVuY2Ugb3V0cHV0cy5cbiAgICogVXNlcnMgZG9uJ3QgbmVlZCB0byBwcm92aWRlIHRoaXMgZnVuY3Rpb24uXG4gICAqIC0gYGRpc3Bvc2VgOiBhbiBvcHRpb25hbCBmdW5jdGlvbiB0byBkaXNwb3NlIHRoZSB0ZW5zb3IgZGF0YSBvbiB0aGUgV2ViTk4gTUxUZW5zb3IuIElmIG9taXR0ZWQsIHRoZSBNTFRlbnNvciB3aWxsXG4gICAqIG5vdCBiZSBkaXNwb3NlZC4gVXN1YWxseSwgdGhpcyBpcyBwcm92aWRlZCBieSB0aGUgV2ViTk4gYmFja2VuZCBmb3IgdGhlIGluZmVyZW5jZSBvdXRwdXRzLiBVc2VycyBkb24ndCBuZWVkIHRvXG4gICAqIHByb3ZpZGUgdGhpcyBmdW5jdGlvbi5cbiAgICpcbiAgICogQHJldHVybnMgYSB0ZW5zb3Igb2JqZWN0XG4gICAqL1xuICBmcm9tTUxUZW5zb3I8VCBleHRlbmRzIFRlbnNvci5NTFRlbnNvckRhdGFUeXBlcz4oXG4gICAgdGVuc29yOiBUZW5zb3IuTUxUZW5zb3JUeXBlLFxuICAgIG9wdGlvbnM6IFRlbnNvckZyb21NTFRlbnNvck9wdGlvbnM8VD4sXG4gICk6IFR5cGVkVGVuc29yPFQ+O1xuXG4gIC8qKlxuICAgKiBjcmVhdGUgYSB0ZW5zb3IgZnJvbSBhIHByZS1hbGxvY2F0ZWQgYnVmZmVyLiBUaGUgYnVmZmVyIHdpbGwgYmUgdXNlZCBhcyBhIHBpbm5lZCBidWZmZXIuXG4gICAqXG4gICAqIEBwYXJhbSB0eXBlIC0gdGhlIHRlbnNvciBlbGVtZW50IHR5cGUuXG4gICAqIEBwYXJhbSBidWZmZXIgLSBhIFR5cGVkQXJyYXkgY29ycmVzcG9uZGluZyB0byB0aGUgdHlwZS5cbiAgICogQHBhcmFtIGRpbXMgLSBzcGVjaWZ5IHRoZSBkaW1lbnNpb24gb2YgdGhlIHRlbnNvci4gSWYgb21pdHRlZCwgYSAxLUQgdGVuc29yIGlzIGFzc3VtZWQuXG4gICAqXG4gICAqIEByZXR1cm5zIGEgdGVuc29yIG9iamVjdFxuICAgKi9cbiAgZnJvbVBpbm5lZEJ1ZmZlcjxUIGV4dGVuZHMgRXhjbHVkZTxUZW5zb3IuVHlwZSwgJ3N0cmluZyc+PihcbiAgICB0eXBlOiBULFxuICAgIGJ1ZmZlcjogVGVuc29yLkRhdGFUeXBlTWFwW1RdLFxuICAgIGRpbXM/OiByZWFkb25seSBudW1iZXJbXSxcbiAgKTogVHlwZWRUZW5zb3I8VD47XG59XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbi8qKlxuICogQSBzdHJpbmcgdGhhdCByZXByZXNlbnRzIGEgZmlsZSdzIFVSTCBvciBwYXRoLlxuICpcbiAqIFBhdGggaXMgdmFpbGFibGUgb25seSBpbiBvbm54cnVudGltZS1ub2RlIG9yIG9ubnhydW50aW1lLXdlYiBydW5uaW5nIGluIE5vZGUuanMuXG4gKi9cbmV4cG9ydCB0eXBlIEZpbGVVcmxPclBhdGggPSBzdHJpbmc7XG5cbi8qKlxuICogQSBCbG9iIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgYSBmaWxlLlxuICovXG5leHBvcnQgdHlwZSBGaWxlQmxvYiA9IEJsb2I7XG5cbi8qKlxuICogQSBVaW50OEFycmF5LCBBcnJheUJ1ZmZlciBvciBTaGFyZWRBcnJheUJ1ZmZlciBvYmplY3QgdGhhdCByZXByZXNlbnRzIGEgZmlsZSBjb250ZW50LlxuICpcbiAqIFdoZW4gaXQgaXMgYW4gQXJyYXlCdWZmZXIgb3IgU2hhcmVkQXJyYXlCdWZmZXIsIHRoZSB3aG9sZSBidWZmZXIgaXMgYXNzdW1lZCB0byBiZSB0aGUgZmlsZSBjb250ZW50LlxuICovXG5leHBvcnQgdHlwZSBGaWxlRGF0YSA9IFVpbnQ4QXJyYXkgfCBBcnJheUJ1ZmZlckxpa2U7XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIGZpbGUgdGhhdCBjYW4gYmUgbG9hZGVkIGJ5IHRoZSBPTk5YIFJ1bnRpbWUgSmF2YVNjcmlwdCBBUEkuXG4gKi9cbmV4cG9ydCB0eXBlIEZpbGVUeXBlID0gRmlsZVVybE9yUGF0aCB8IEZpbGVCbG9iIHwgRmlsZURhdGE7XG5cbi8qKlxuICogUmVwcmVzZW50cyBhbiBleHRlcm5hbCBkYXRhIGZpbGUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRXh0ZXJuYWxEYXRhRmlsZURlc2NyaXB0aW9uIHtcbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIGV4dGVybmFsIGRhdGEgZmlsZS5cbiAgICovXG4gIGRhdGE6IEZpbGVUeXBlO1xuICAvKipcbiAgICogU3BlY2lmeSB0aGUgZmlsZSBwYXRoLlxuICAgKi9cbiAgcGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgYW4gZXh0ZXJuYWwgZGF0YSBmaWxlLlxuICpcbiAqIFdoZW4gdXNpbmcgYSBzdHJpbmcsIGl0IHNob3VsZCBiZSBhIGZpbGUgVVJMIG9yIHBhdGggdGhhdCBpbiB0aGUgc2FtZSBkaXJlY3RvcnkgYXMgdGhlIG1vZGVsIGZpbGUuXG4gKi9cbmV4cG9ydCB0eXBlIEV4dGVybmFsRGF0YUZpbGVUeXBlID0gRXh0ZXJuYWxEYXRhRmlsZURlc2NyaXB0aW9uIHwgRmlsZVVybE9yUGF0aDtcblxuLyoqXG4gKiBPcHRpb25zIGZvciBtb2RlbCBsb2FkaW5nLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE9ubnhNb2RlbE9wdGlvbnMge1xuICAvKipcbiAgICogU3BlY2lmeWluZyBhIGxpc3Qgb2YgZmlsZXMgdGhhdCByZXByZXNlbnRzIHRoZSBleHRlcm5hbCBkYXRhLlxuICAgKi9cbiAgZXh0ZXJuYWxEYXRhPzogcmVhZG9ubHkgRXh0ZXJuYWxEYXRhRmlsZVR5cGVbXTtcbn1cbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yIH0gZnJvbSAnLi90ZW5zb3IuanMnO1xuXG5leHBvcnQgdHlwZSBOb25UZW5zb3JUeXBlID0gbmV2ZXI7XG5cbi8qKlxuICogVHlwZSBPbm54VmFsdWUgUmVwcmVzZW50cyBib3RoIHRlbnNvcnMgYW5kIG5vbi10ZW5zb3JzIHZhbHVlIGZvciBtb2RlbCdzIGlucHV0cy9vdXRwdXRzLlxuICpcbiAqIE5PVEU6IGN1cnJlbnRseSBub3Qgc3VwcG9ydCBub24tdGVuc29yXG4gKi9cbmV4cG9ydCB0eXBlIE9ubnhWYWx1ZSA9IFRlbnNvciB8IE5vblRlbnNvclR5cGU7XG5cbi8qKlxuICogVHlwZSBPbm54VmFsdWVEYXRhTG9jYXRpb24gcmVwcmVzZW50cyB0aGUgbG9jYXRpb24gb2YgdGhlIGRhdGEgb2YgYW4gT25ueFZhbHVlLlxuICovXG5leHBvcnQgdHlwZSBPbm54VmFsdWVEYXRhTG9jYXRpb24gPSBUZW5zb3IuRGF0YUxvY2F0aW9uO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vKipcbiAqICMgT05OWCBSdW50aW1lIEphdmFTY3JpcHQgQVBJXG4gKlxuICogT05OWCBSdW50aW1lIEphdmFTY3JpcHQgQVBJIGlzIGEgdW5pZmllZCBBUEkgZm9yIGFsbCBKYXZhU2NyaXB0IHVzYWdlcywgaW5jbHVkaW5nIHRoZSBmb2xsb3dpbmcgTlBNIHBhY2thZ2VzOlxuICpcbiAqIC0gW29ubnhydW50aW1lLW5vZGVdKGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL29ubnhydW50aW1lLW5vZGUpXG4gKiAtIFtvbm54cnVudGltZS13ZWJdKGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL29ubnhydW50aW1lLXdlYilcbiAqIC0gW29ubnhydW50aW1lLXJlYWN0LW5hdGl2ZV0oaHR0cHM6Ly93d3cubnBtanMuY29tL3BhY2thZ2Uvb25ueHJ1bnRpbWUtcmVhY3QtbmF0aXZlKVxuICpcbiAqIFNlZSBhbHNvOlxuICogLSBbR2V0IFN0YXJ0ZWRdKGh0dHBzOi8vb25ueHJ1bnRpbWUuYWkvZG9jcy9nZXQtc3RhcnRlZC93aXRoLWphdmFzY3JpcHQvKVxuICogLSBbSW5mZXJlbmNlIGV4YW1wbGVzXShodHRwczovL2dpdGh1Yi5jb20vbWljcm9zb2Z0L29ubnhydW50aW1lLWluZmVyZW5jZS1leGFtcGxlcy90cmVlL21haW4vanMpXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9iYWNrZW5kLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vZW52LmpzJztcbmV4cG9ydCAqIGZyb20gJy4vaW5mZXJlbmNlLXNlc3Npb24uanMnO1xuZXhwb3J0ICogZnJvbSAnLi90ZW5zb3IuanMnO1xuZXhwb3J0ICogZnJvbSAnLi90ZW5zb3ItY29udmVyc2lvbi5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3RlbnNvci1mYWN0b3J5LmpzJztcbmV4cG9ydCAqIGZyb20gJy4vdHJhY2UuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9vbm54LW1vZGVsLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vb25ueC12YWx1ZS5qcyc7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmV4cG9ydCBjb25zdCBpc05vZGUgPSAhISh0eXBlb2YgcHJvY2VzcyAhPT0gJ3VuZGVmaW5lZCcgJiYgcHJvY2Vzcy52ZXJzaW9ucyAmJiBwcm9jZXNzLnZlcnNpb25zLm5vZGUpO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vLy8gPHJlZmVyZW5jZSBsaWI9XCJ3ZWJ3b3JrZXJcIiAvPlxuXG4vL1xuLy8gKiB0eXBlIGhhY2sgZm9yIFwiSFRNTEltYWdlRWxlbWVudFwiXG4vL1xuLy8gaW4gdHlwZXNjcmlwdCwgdGhlIHR5cGUgb2YgXCJIVE1MSW1hZ2VFbGVtZW50XCIgaXMgZGVmaW5lZCBpbiBsaWIuZG9tLmQudHMsIHdoaWNoIGlzIGNvbmZsaWN0IHdpdGggbGliLndlYndvcmtlci5kLnRzLlxuLy8gd2hlbiB3ZSB1c2Ugd2Vid29ya2VyLCB0aGUgbGliLndlYndvcmtlci5kLnRzIHdpbGwgYmUgdXNlZCwgd2hpY2ggZG9lcyBub3QgaGF2ZSBIVE1MSW1hZ2VFbGVtZW50IGRlZmluZWQuXG4vL1xuLy8gd2Ugd2lsbCBnZXQgdGhlIGZvbGxvd2luZyBlcnJvcnMgY29tcGxhaW5pbmcgdGhhdCBIVE1MSW1hZ2VFbGVtZW50IGlzIG5vdCBkZWZpbmVkOlxuLy9cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vL1xuLy8gLi4vY29tbW9uL2Rpc3QvY2pzL3RlbnNvci1mYWN0b3J5LmQudHM6MTg3OjI5IC0gZXJyb3IgVFMyNTUyOiBDYW5ub3QgZmluZCBuYW1lICdIVE1MSW1hZ2VFbGVtZW50Jy4gRGlkIHlvdSBtZWFuXG4vLyAnSFRNTExJRWxlbWVudCc/XG4vL1xuLy8gMTg3ICAgICBmcm9tSW1hZ2UoaW1hZ2VFbGVtZW50OiBIVE1MSW1hZ2VFbGVtZW50LCBvcHRpb25zPzogVGVuc29yRnJvbUltYWdlRWxlbWVudE9wdGlvbnMpOlxuLy8gUHJvbWlzZTxUeXBlZFRlbnNvcjwnZmxvYXQzMic+IHwgVHlwZWRUZW5zb3I8J3VpbnQ4Jz4+O1xuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB+fn5+fn5+fn5+fn5+fn5+XG4vL1xuLy8gbm9kZV9tb2R1bGVzL0B3ZWJncHUvdHlwZXMvZGlzdC9pbmRleC5kLnRzOjgzOjcgLSBlcnJvciBUUzI1NTI6IENhbm5vdCBmaW5kIG5hbWUgJ0hUTUxJbWFnZUVsZW1lbnQnLiBEaWQgeW91IG1lYW5cbi8vICdIVE1MTElFbGVtZW50Jz9cbi8vXG4vLyA4MyAgICAgfCBIVE1MSW1hZ2VFbGVtZW50XG4vLyAgICAgICAgICB+fn5+fn5+fn5+fn5+fn5+XG4vL1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vXG4vLyBgSFRNTEltYWdlRWxlbWVudGAgaXMgb25seSB1c2VkIGluIHR5cGUgZGVjbGFyYXRpb24gYW5kIG5vdCBpbiByZWFsIGNvZGUuIFNvIHdlIGRlZmluZSBpdCBhcyBgdW5rbm93bmAgaGVyZSB0b1xuLy8gYnlwYXNzIHRoZSB0eXBlIGNoZWNrLlxuXG4vL1xuLy8gKiB0eXBlIGhhY2sgZm9yIFwiZG9jdW1lbnRcIlxuLy9cbi8vIGluIHR5cGVzY3JpcHQsIHRoZSB0eXBlIG9mIFwiZG9jdW1lbnRcIiBpcyBkZWZpbmVkIGluIGxpYi5kb20uZC50cywgc28gaXQncyBub3QgYXZhaWxhYmxlIGluIHdlYndvcmtlci5cbi8vXG4vLyB3ZSB3aWxsIGdldCB0aGUgZm9sbG93aW5nIGVycm9ycyBjb21wbGFpbmluZyB0aGF0IGRvY3VtZW50IGlzIG5vdCBkZWZpbmVkOlxuLy9cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vL1xuLy8gbGliL3dhc20vd2FzbS11dGlscy1pbXBvcnQudHM6NzozMyAtIGVycm9yIFRTMjU4NDogQ2Fubm90IGZpbmQgbmFtZSAnZG9jdW1lbnQnLiBEbyB5b3UgbmVlZCB0byBjaGFuZ2UgeW91ciB0YXJnZXRcbi8vIGxpYnJhcnk/IFRyeSBjaGFuZ2luZyB0aGUgJ2xpYicgY29tcGlsZXIgb3B0aW9uIHRvIGluY2x1ZGUgJ2RvbScuXG4vL1xuLy8gNyBleHBvcnQgY29uc3Qgc2NyaXB0U3JjID0gdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyA/IChkb2N1bWVudD8uY3VycmVudFNjcmlwdCBhcyBIVE1MU2NyaXB0RWxlbWVudCk/LnNyYyA6XG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfn5+fn5+fn5cbi8vXG4vLyBsaWIvd2FzbS93YXNtLXV0aWxzLWltcG9ydC50czo3OjYxIC0gZXJyb3IgVFMyNTg0OiBDYW5ub3QgZmluZCBuYW1lICdkb2N1bWVudCcuIERvIHlvdSBuZWVkIHRvIGNoYW5nZSB5b3VyIHRhcmdldFxuLy8gbGlicmFyeT8gVHJ5IGNoYW5naW5nIHRoZSAnbGliJyBjb21waWxlciBvcHRpb24gdG8gaW5jbHVkZSAnZG9tJy5cbi8vXG4vLyA3IGV4cG9ydCBjb25zdCBzY3JpcHRTcmMgPSB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnID8gKGRvY3VtZW50Py5jdXJyZW50U2NyaXB0IGFzIEhUTUxTY3JpcHRFbGVtZW50KT8uc3JjIDpcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfn5+fn5+fn5cbi8vXG4vLyBsaWIvd2FzbS93YXNtLXV0aWxzLWltcG9ydC50czo3Ojg4IC0gZXJyb3IgVFMyNTUyOiBDYW5ub3QgZmluZCBuYW1lICdIVE1MU2NyaXB0RWxlbWVudCcuIERpZCB5b3UgbWVhblxuLy8gJ0hUTUxMSUVsZW1lbnQnP1xuLy9cbi8vIDcgZXhwb3J0IGNvbnN0IHNjcmlwdFNyYyA9IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgPyAoZG9jdW1lbnQ/LmN1cnJlbnRTY3JpcHQgYXMgSFRNTFNjcmlwdEVsZW1lbnQpPy5zcmMgOlxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB+fn5+fn5+fn5+fn5+fn5+flxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vXG4vLyBgZG9jdW1lbnRgIGlzIHVzZWQgdG8gZ2V0IHRoZSBjdXJyZW50IHNjcmlwdCBVUkwsIHdoaWNoIGlzIG5vdCBhdmFpbGFibGUgaW4gd2Vid29ya2VyLiBUaGlzIGZpbGUgaXMgc2VydmVkIGFzIGFcbi8vIFwiZHVhbFwiIGZpbGUgZm9yIGVudHJpZXMgb2YgYm90aCB3ZWJ3b3JrZXIgYW5kIHRoZSBlc20gbW9kdWxlLlxuLy9cbmRlY2xhcmUgZ2xvYmFsIHtcbiAgdHlwZSBIVE1MSW1hZ2VFbGVtZW50ID0gdW5rbm93bjtcbiAgdHlwZSBIVE1MU2NyaXB0RWxlbWVudCA9IHsgc3JjPzogc3RyaW5nIH07XG4gIGNvbnN0IGRvY3VtZW50OiB1bmRlZmluZWQgfCB7IGN1cnJlbnRTY3JpcHQ/OiBIVE1MU2NyaXB0RWxlbWVudCB9O1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5XG4gKlxuICogVGhpcyBmaWxlIGlzIHNlcnZlZCBhcyBhIFwiZHVhbFwiIGZpbGUgZm9yIGJvdGggZW50cmllcyBvZiB0aGUgZm9sbG93aW5nOlxuICogLSBUaGUgcHJveHkgd29ya2VyIGl0c2VsZi5cbiAqICAgLSBXaGVuIHVzZWQgYXMgYSB3b3JrZXIsIGl0IGxpc3RlbnMgdG8gdGhlIG1lc3NhZ2VzIGZyb20gdGhlIG1haW4gdGhyZWFkIGFuZCBwZXJmb3JtcyB0aGUgY29ycmVzcG9uZGluZyBvcGVyYXRpb25zLlxuICogICAtIFNob3VsZCBiZSBpbXBvcnRlZCBkaXJlY3RseSB1c2luZyBgbmV3IFdvcmtlcigpYCBpbiB0aGUgbWFpbiB0aHJlYWQuXG4gKlxuICogLSBUaGUgRVNNIG1vZHVsZSB0aGF0IGNyZWF0ZXMgdGhlIHByb3h5IHdvcmtlciAoYXMgYSB3b3JrZXIgbGF1bmNoZXIpLlxuICogICAtIFdoZW4gdXNlZCBhcyBhIHdvcmtlciBsYXVuY2hlciwgaXQgY3JlYXRlcyB0aGUgcHJveHkgd29ya2VyIGFuZCByZXR1cm5zIGl0LlxuICogICAtIFNob3VsZCBiZSBpbXBvcnRlZCB1c2luZyBgaW1wb3J0KClgIGluIHRoZSBtYWluIHRocmVhZCwgd2l0aCB0aGUgcXVlcnkgcGFyYW1ldGVyIGBpbXBvcnQ9MWAuXG4gKlxuICogVGhpcyBmaWxlIHdpbGwgYmUgYWx3YXlzIGNvbXBpbGluZyBpbnRvIEVTTSBmb3JtYXQuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBPcnRXYXNtTWVzc2FnZSwgU2VyaWFsaXphYmxlVGVuc29yTWV0YWRhdGEgfSBmcm9tICcuLi9wcm94eS1tZXNzYWdlcy5qcyc7XG5pbXBvcnQge1xuICBjcmVhdGVTZXNzaW9uLFxuICBjb3B5RnJvbUV4dGVybmFsQnVmZmVyLFxuICBlbmRQcm9maWxpbmcsXG4gIGV4dHJhY3RUcmFuc2ZlcmFibGVCdWZmZXJzLFxuICBpbml0RXAsXG4gIGluaXRSdW50aW1lLFxuICByZWxlYXNlU2Vzc2lvbixcbiAgcnVuLFxufSBmcm9tICcuLi93YXNtLWNvcmUtaW1wbC5qcyc7XG5pbXBvcnQgeyBpbml0aWFsaXplV2ViQXNzZW1ibHkgfSBmcm9tICcuLi93YXNtLWZhY3RvcnkuanMnO1xuaW1wb3J0IHsgc2NyaXB0U3JjIH0gZnJvbSAnLi4vd2FzbS11dGlscy1pbXBvcnQuanMnO1xuXG5jb25zdCBXT1JLRVJfTkFNRSA9ICdvcnQtd2FzbS1wcm94eS13b3JrZXInO1xuY29uc3QgaXNQcm94eVdvcmtlciA9IGdsb2JhbFRoaXMuc2VsZj8ubmFtZSA9PT0gV09SS0VSX05BTUU7XG5cbmlmIChpc1Byb3h5V29ya2VyKSB7XG4gIC8vIFdvcmtlciB0aHJlYWRcbiAgc2VsZi5vbm1lc3NhZ2UgPSAoZXY6IE1lc3NhZ2VFdmVudDxPcnRXYXNtTWVzc2FnZT4pOiB2b2lkID0+IHtcbiAgICBjb25zdCB7IHR5cGUsIGluOiBtZXNzYWdlIH0gPSBldi5kYXRhO1xuICAgIHRyeSB7XG4gICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgY2FzZSAnaW5pdC13YXNtJzpcbiAgICAgICAgICBpbml0aWFsaXplV2ViQXNzZW1ibHkobWVzc2FnZSEud2FzbSkudGhlbihcbiAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgaW5pdFJ1bnRpbWUobWVzc2FnZSEpLnRoZW4oXG4gICAgICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlIH0pO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlLCBlcnIgfSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSwgZXJyIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdpbml0LWVwJzoge1xuICAgICAgICAgIGNvbnN0IHsgZXBOYW1lLCBlbnYgfSA9IG1lc3NhZ2UhO1xuICAgICAgICAgIGluaXRFcChlbnYsIGVwTmFtZSkudGhlbihcbiAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlLCBlcnIgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAnY29weS1mcm9tJzoge1xuICAgICAgICAgIGNvbnN0IHsgYnVmZmVyIH0gPSBtZXNzYWdlITtcbiAgICAgICAgICBjb25zdCBidWZmZXJEYXRhID0gY29weUZyb21FeHRlcm5hbEJ1ZmZlcihidWZmZXIpO1xuICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSwgb3V0OiBidWZmZXJEYXRhIH0gYXMgT3J0V2FzbU1lc3NhZ2UpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ2NyZWF0ZSc6IHtcbiAgICAgICAgICBjb25zdCB7IG1vZGVsLCBvcHRpb25zIH0gPSBtZXNzYWdlITtcbiAgICAgICAgICBjcmVhdGVTZXNzaW9uKG1vZGVsLCBvcHRpb25zKS50aGVuKFxuICAgICAgICAgICAgKHNlc3Npb25NZXRhZGF0YSkgPT4ge1xuICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGUsIG91dDogc2Vzc2lvbk1ldGFkYXRhIH0gYXMgT3J0V2FzbU1lc3NhZ2UpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlLCBlcnIgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAncmVsZWFzZSc6XG4gICAgICAgICAgcmVsZWFzZVNlc3Npb24obWVzc2FnZSEpO1xuICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSB9KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAncnVuJzoge1xuICAgICAgICAgIGNvbnN0IHsgc2Vzc2lvbklkLCBpbnB1dEluZGljZXMsIGlucHV0cywgb3V0cHV0SW5kaWNlcywgb3B0aW9ucyB9ID0gbWVzc2FnZSE7XG4gICAgICAgICAgcnVuKHNlc3Npb25JZCwgaW5wdXRJbmRpY2VzLCBpbnB1dHMsIG91dHB1dEluZGljZXMsIG5ldyBBcnJheShvdXRwdXRJbmRpY2VzLmxlbmd0aCkuZmlsbChudWxsKSwgb3B0aW9ucykudGhlbihcbiAgICAgICAgICAgIChvdXRwdXRzKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChvdXRwdXRzLnNvbWUoKG8pID0+IG9bM10gIT09ICdjcHUnKSkge1xuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSwgZXJyOiAnUHJveHkgZG9lcyBub3Qgc3VwcG9ydCBub24tY3B1IHRlbnNvciBsb2NhdGlvbi4nIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKFxuICAgICAgICAgICAgICAgICAgeyB0eXBlLCBvdXQ6IG91dHB1dHMgfSBhcyBPcnRXYXNtTWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgIGV4dHJhY3RUcmFuc2ZlcmFibGVCdWZmZXJzKFsuLi5pbnB1dHMsIC4uLm91dHB1dHNdIGFzIFNlcmlhbGl6YWJsZVRlbnNvck1ldGFkYXRhW10pLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZSwgZXJyIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ2VuZC1wcm9maWxpbmcnOlxuICAgICAgICAgIGVuZFByb2ZpbGluZyhtZXNzYWdlISk7XG4gICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlIH0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlLCBlcnIgfSBhcyBPcnRXYXNtTWVzc2FnZSk7XG4gICAgfVxuICB9O1xufVxuXG5leHBvcnQgZGVmYXVsdCBpc1Byb3h5V29ya2VyXG4gID8gbnVsbFxuICA6ICh1cmxPdmVycmlkZT86IHN0cmluZykgPT5cbiAgICAgIG5ldyBXb3JrZXIodXJsT3ZlcnJpZGUgPz8gc2NyaXB0U3JjISwgeyB0eXBlOiBCVUlMRF9ERUZTLklTX0VTTSA/ICdtb2R1bGUnIDogJ2NsYXNzaWMnLCBuYW1lOiBXT1JLRVJfTkFNRSB9KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHR5cGUgeyBPcnRXYXNtTW9kdWxlIH0gZnJvbSAnLi93YXNtLXR5cGVzJztcbmltcG9ydCB7IGlzTm9kZSB9IGZyb20gJy4vd2FzbS11dGlscy1lbnYnO1xuXG4vKipcbiAqIFRoZSBvcmlnaW4gb2YgdGhlIGN1cnJlbnQgbG9jYXRpb24uXG4gKlxuICogSW4gTm9kZS5qcywgdGhpcyBpcyB1bmRlZmluZWQuXG4gKi9cbmNvbnN0IG9yaWdpbiA9IGlzTm9kZSB8fCB0eXBlb2YgbG9jYXRpb24gPT09ICd1bmRlZmluZWQnID8gdW5kZWZpbmVkIDogbG9jYXRpb24ub3JpZ2luO1xuXG4vKipcbiAqIFNvbWUgYnVuZGxlcnMgKGVnLiBXZWJwYWNrKSB3aWxsIHJld3JpdGUgYGltcG9ydC5tZXRhLnVybGAgdG8gYSBmaWxlIFVSTCBhdCBjb21waWxlIHRpbWUuXG4gKlxuICogVGhpcyBmdW5jdGlvbiBjaGVja3MgaWYgYGltcG9ydC5tZXRhLnVybGAgc3RhcnRzIHdpdGggYGZpbGU6YCwgYnV0IHVzaW5nIHRoZSBgPmAgYW5kIGA8YCBvcGVyYXRvcnMgaW5zdGVhZCBvZlxuICogYHN0YXJ0c1dpdGhgIGZ1bmN0aW9uIHNvIHRoYXQgY29kZSBtaW5pbWl6ZXJzIGNhbiByZW1vdmUgdGhlIGRlYWQgY29kZSBjb3JyZWN0bHkuXG4gKlxuICogRm9yIGV4YW1wbGUsIGlmIHdlIHVzZSB0ZXJzZXIgdG8gbWluaWZ5IHRoZSBmb2xsb3dpbmcgY29kZTpcbiAqIGBgYGpzXG4gKiBpZiAoXCJmaWxlOi8vaGFyZC1jb2RlZC1maWxlbmFtZVwiLnN0YXJ0c1dpdGgoXCJmaWxlOlwiKSkge1xuICogICBjb25zb2xlLmxvZygxKVxuICogfSBlbHNlIHtcbiAqICAgY29uc29sZS5sb2coMilcbiAqIH1cbiAqXG4gKiBpZiAoXCJmaWxlOi8vaGFyZC1jb2RlZC1maWxlbmFtZVwiID4gXCJmaWxlOlwiICYmIFwiZmlsZTovL2hhcmQtY29kZWQtZmlsZW5hbWVcIiA8IFwiZmlsZTtcIikge1xuICogICBjb25zb2xlLmxvZygzKVxuICogfSBlbHNlIHtcbiAqICAgY29uc29sZS5sb2coNClcbiAqIH1cbiAqIGBgYFxuICpcbiAqIFRoZSBtaW5pZmllZCBjb2RlIHdpbGwgYmU6XG4gKiBgYGBqc1xuICogXCJmaWxlOi8vaGFyZC1jb2RlZC1maWxlbmFtZVwiLnN0YXJ0c1dpdGgoXCJmaWxlOlwiKT9jb25zb2xlLmxvZygxKTpjb25zb2xlLmxvZygyKSxjb25zb2xlLmxvZygzKTtcbiAqIGBgYFxuICpcbiAqICh1c2UgVGVyc2VyIDUuMzkuMCB3aXRoIGRlZmF1bHQgb3B0aW9ucywgaHR0cHM6Ly90cnkudGVyc2VyLm9yZy8pXG4gKlxuICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgaW1wb3J0Lm1ldGEudXJsIGlzIGhhcmRjb2RlZCBhcyBhIGZpbGUgVVJJLlxuICovXG5leHBvcnQgY29uc3QgaXNFc21JbXBvcnRNZXRhVXJsSGFyZGNvZGVkQXNGaWxlVXJpID1cbiAgQlVJTERfREVGUy5JU19FU00gJiYgQlVJTERfREVGUy5FU01fSU1QT1JUX01FVEFfVVJMISA+ICdmaWxlOicgJiYgQlVJTERfREVGUy5FU01fSU1QT1JUX01FVEFfVVJMISA8ICdmaWxlOyc7XG5cbmNvbnN0IGdldFNjcmlwdFNyYyA9ICgpOiBzdHJpbmcgfCB1bmRlZmluZWQgPT4ge1xuICAvLyBpZiBOb2RlanMsIHJldHVybiB1bmRlZmluZWRcbiAgaWYgKGlzTm9kZSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgLy8gaWYgSXQncyBFU00sIHVzZSBpbXBvcnQubWV0YS51cmxcbiAgaWYgKEJVSUxEX0RFRlMuSVNfRVNNKSB7XG4gICAgLy8gRm9yIEVTTSwgaWYgdGhlIGltcG9ydC5tZXRhLnVybCBpcyBhIGZpbGUgVVJMLCB0aGlzIHVzdWFsbHkgbWVhbnMgdGhlIGJ1bmRsZXIgcmV3cml0ZXMgYGltcG9ydC5tZXRhLnVybGAgdG9cbiAgICAvLyB0aGUgZmlsZSBwYXRoIGF0IGNvbXBpbGUgdGltZS4gSW4gdGhpcyBjYXNlLCB0aGlzIGZpbGUgcGF0aCBjYW5ub3QgYmUgdXNlZCB0byBkZXRlcm1pbmUgdGhlIHJ1bnRpbWUgVVJMLlxuICAgIC8vXG4gICAgLy8gV2UgbmVlZCB0byB1c2UgdGhlIFVSTCBjb25zdHJ1Y3RvciBsaWtlIHRoaXM6XG4gICAgLy8gYGBganNcbiAgICAvLyBuZXcgVVJMKCdhY3R1YWwtYnVuZGxlLW5hbWUuanMnLCBpbXBvcnQubWV0YS51cmwpLmhyZWZcbiAgICAvLyBgYGBcbiAgICAvLyBTbyB0aGF0IGJ1bmRsZXIgY2FuIHByZXByb2Nlc3MgdGhlIFVSTCBjb3JyZWN0bHkuXG4gICAgaWYgKGlzRXNtSW1wb3J0TWV0YVVybEhhcmRjb2RlZEFzRmlsZVVyaSkge1xuICAgICAgLy8gaWYgdGhlIHJld3JpdHRlbiBVUkwgaXMgYSByZWxhdGl2ZSBwYXRoLCB3ZSBuZWVkIHRvIHVzZSB0aGUgb3JpZ2luIHRvIHJlc29sdmUgdGhlIFVSTC5cblxuICAgICAgLy8gVGhlIGZvbGxvd2luZyBpcyBhIHdvcmthcm91bmQgZm9yIFZpdGUuXG4gICAgICAvL1xuICAgICAgLy8gVml0ZSB1c2VzIGEgYnVuZGxlcihyb2xsdXAvcm9sbGRvd24pIHRoYXQgZG9lcyBub3QgcmV3cml0ZSBgaW1wb3J0Lm1ldGEudXJsYCB0byBhIGZpbGUgVVJMLiBTbyBpbiB0aGVvcnksIHRoaXNcbiAgICAgIC8vIGNvZGUgcGF0aCBzaG91bGQgbm90IGJlIGV4ZWN1dGVkIGluIFZpdGUuIEhvd2V2ZXIsIHRoZSBidW5kbGVyIGRvZXMgbm90IGtub3cgaXQgYW5kIGl0IHN0aWxsIHRyeSB0byBsb2FkIHRoZVxuICAgICAgLy8gZm9sbG93aW5nIHBhdHRlcm46XG4gICAgICAvLyAtIGByZXR1cm4gbmV3IFVSTCgnZmlsZW5hbWUnLCBpbXBvcnQubWV0YS51cmwpLmhyZWZgXG4gICAgICAvL1xuICAgICAgLy8gQnkgcmVwbGFjaW5nIHRoZSBwYXR0ZXJuIGFib3ZlIHdpdGggdGhlIGZvbGxvd2luZyBjb2RlLCB3ZSBjYW4gc2tpcCB0aGUgcmVzb3VyY2UgbG9hZGluZyBiZWhhdmlvcjpcbiAgICAgIC8vIC0gYGNvbnN0IFVSTDIgPSBVUkw7IHJldHVybiBuZXcgVVJMMignZmlsZW5hbWUnLCBpbXBvcnQubWV0YS51cmwpLmhyZWY7YFxuICAgICAgLy9cbiAgICAgIC8vIEFuZCBpdCBzdGlsbCB3b3JrcyBpbiBXZWJwYWNrLlxuICAgICAgY29uc3QgVVJMMiA9IFVSTDtcbiAgICAgIHJldHVybiBuZXcgVVJMKG5ldyBVUkwyKEJVSUxEX0RFRlMuQlVORExFX0ZJTEVOQU1FLCBCVUlMRF9ERUZTLkVTTV9JTVBPUlRfTUVUQV9VUkwpLmhyZWYsIG9yaWdpbikuaHJlZjtcbiAgICB9XG5cbiAgICByZXR1cm4gQlVJTERfREVGUy5FU01fSU1QT1JUX01FVEFfVVJMO1xuICB9XG5cbiAgcmV0dXJuIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCdcbiAgICA/IChkb2N1bWVudC5jdXJyZW50U2NyaXB0IGFzIEhUTUxTY3JpcHRFbGVtZW50KT8uc3JjXG4gICAgOiAvLyB1c2UgYHNlbGYubG9jYXRpb24uaHJlZmAgaWYgYXZhaWxhYmxlXG4gICAgICB0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgID8gc2VsZi5sb2NhdGlvbj8uaHJlZlxuICAgICAgOiB1bmRlZmluZWQ7XG59O1xuXG4vKipcbiAqIFRoZSBjbGFzc2ljIHNjcmlwdCBzb3VyY2UgVVJMLiBUaGlzIGlzIG5vdCBhbHdheXMgYXZhaWxhYmxlIGluIG5vbiBFU01vZHVsZSBlbnZpcm9ubWVudHMuXG4gKlxuICogSW4gTm9kZS5qcywgdGhpcyBpcyB1bmRlZmluZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBzY3JpcHRTcmMgPSBnZXRTY3JpcHRTcmMoKTtcblxuLyoqXG4gKiBJbmZlciB0aGUgd2FzbSBwYXRoIHByZWZpeCBmcm9tIHRoZSBzY3JpcHQgc291cmNlIFVSTC5cbiAqXG4gKiBAcmV0dXJucyBUaGUgaW5mZXJyZWQgd2FzbSBwYXRoIHByZWZpeCwgb3IgdW5kZWZpbmVkIGlmIHRoZSBzY3JpcHQgc291cmNlIFVSTCBpcyBub3QgYXZhaWxhYmxlIG9yIGlzIGEgYmxvYiBVUkwuXG4gKi9cbmV4cG9ydCBjb25zdCBpbmZlcldhc21QYXRoUHJlZml4RnJvbVNjcmlwdFNyYyA9ICgpOiBzdHJpbmcgfCB1bmRlZmluZWQgPT4ge1xuICBpZiAoc2NyaXB0U3JjICYmICFzY3JpcHRTcmMuc3RhcnRzV2l0aCgnYmxvYjonKSkge1xuICAgIHJldHVybiBzY3JpcHRTcmMuc3Vic3RyaW5nKDAsIHNjcmlwdFNyYy5sYXN0SW5kZXhPZignLycpICsgMSk7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn07XG5cbi8qKlxuICogQ2hlY2sgaWYgdGhlIGdpdmVuIGZpbGVuYW1lIHdpdGggcHJlZml4IGlzIGZyb20gdGhlIHNhbWUgb3JpZ2luLlxuICovXG5jb25zdCBpc1NhbWVPcmlnaW4gPSAoZmlsZW5hbWU6IHN0cmluZywgcHJlZml4T3ZlcnJpZGU/OiBzdHJpbmcpID0+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBiYXNlVXJsID0gcHJlZml4T3ZlcnJpZGUgPz8gc2NyaXB0U3JjO1xuICAgIGNvbnN0IHVybCA9IGJhc2VVcmwgPyBuZXcgVVJMKGZpbGVuYW1lLCBiYXNlVXJsKSA6IG5ldyBVUkwoZmlsZW5hbWUpO1xuICAgIHJldHVybiB1cmwub3JpZ2luID09PSBvcmlnaW47XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufTtcblxuLyoqXG4gKiBOb3JtYWxpemUgdGhlIGlucHV0cyB0byBhbiBhYnNvbHV0ZSBVUkwgd2l0aCB0aGUgZ2l2ZW4gcHJlZml4IG92ZXJyaWRlLiBJZiBmYWlsZWQsIHJldHVybiB1bmRlZmluZWQuXG4gKi9cbmNvbnN0IG5vcm1hbGl6ZVVybCA9IChmaWxlbmFtZTogc3RyaW5nLCBwcmVmaXhPdmVycmlkZT86IHN0cmluZykgPT4ge1xuICBjb25zdCBiYXNlVXJsID0gcHJlZml4T3ZlcnJpZGUgPz8gc2NyaXB0U3JjO1xuICB0cnkge1xuICAgIGNvbnN0IHVybCA9IGJhc2VVcmwgPyBuZXcgVVJMKGZpbGVuYW1lLCBiYXNlVXJsKSA6IG5ldyBVUkwoZmlsZW5hbWUpO1xuICAgIHJldHVybiB1cmwuaHJlZjtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufTtcblxuLyoqXG4gKiBDcmVhdGUgYSBmYWxsYmFjayBVUkwgaWYgYW4gYWJzb2x1dGUgVVJMIGNhbm5vdCBiZSBjcmVhdGVkIGJ5IHRoZSBub3JtYWxpemVVcmwgZnVuY3Rpb24uXG4gKi9cbmNvbnN0IGZhbGxiYWNrVXJsID0gKGZpbGVuYW1lOiBzdHJpbmcsIHByZWZpeE92ZXJyaWRlPzogc3RyaW5nKSA9PiBgJHtwcmVmaXhPdmVycmlkZSA/PyAnLi8nfSR7ZmlsZW5hbWV9YDtcblxuLyoqXG4gKiBUaGlzIGhlbHBlciBmdW5jdGlvbiBpcyB1c2VkIHRvIHByZWxvYWQgYSBtb2R1bGUgZnJvbSBhIFVSTC5cbiAqXG4gKiBJZiB0aGUgb3JpZ2luIG9mIHRoZSB3b3JrZXIgVVJMIGlzIGRpZmZlcmVudCBmcm9tIHRoZSBjdXJyZW50IG9yaWdpbiwgdGhlIHdvcmtlciBjYW5ub3QgYmUgbG9hZGVkIGRpcmVjdGx5LlxuICogU2VlIGRpc2N1c3Npb25zIGluIGh0dHBzOi8vZ2l0aHViLmNvbS93ZWJwYWNrLWNvbnRyaWIvd29ya2VyLWxvYWRlci9pc3N1ZXMvMTU0XG4gKlxuICogSW4gdGhpcyBjYXNlLCB3ZSB3aWxsIGZldGNoIHRoZSB3b3JrZXIgVVJMIGFuZCBjcmVhdGUgYSBuZXcgQmxvYiBVUkwgd2l0aCB0aGUgc2FtZSBvcmlnaW4gYXMgYSB3b3JrYXJvdW5kLlxuICpcbiAqIEBwYXJhbSBhYnNvbHV0ZVVybCAtIFRoZSBhYnNvbHV0ZSBVUkwgdG8gcHJlbG9hZC5cbiAqXG4gKiBAcmV0dXJucyAtIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgbmV3IEJsb2IgVVJMXG4gKi9cbmNvbnN0IHByZWxvYWQgPSBhc3luYyAoYWJzb2x1dGVVcmw6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiA9PiB7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYWJzb2x1dGVVcmwsIHsgY3JlZGVudGlhbHM6ICdzYW1lLW9yaWdpbicgfSk7XG4gIGNvbnN0IGJsb2IgPSBhd2FpdCByZXNwb25zZS5ibG9iKCk7XG4gIHJldHVybiBVUkwuY3JlYXRlT2JqZWN0VVJMKGJsb2IpO1xufTtcblxuLyoqXG4gKiBUaGlzIGhlbHBlciBmdW5jdGlvbiBpcyB1c2VkIHRvIGR5bmFtaWNhbGx5IGltcG9ydCBhIG1vZHVsZSBmcm9tIGEgVVJMLlxuICpcbiAqIFRoZSBidWlsZCBzY3JpcHQgaGFzIHNwZWNpYWwgaGFuZGxpbmcgZm9yIHRoaXMgZnVuY3Rpb24gdG8gZW5zdXJlIHRoYXQgdGhlIFVSTCBpcyBub3QgYnVuZGxlZCBpbnRvIHRoZSBmaW5hbCBvdXRwdXQuXG4gKlxuICogQHBhcmFtIHVybCAtIFRoZSBVUkwgdG8gaW1wb3J0LlxuICpcbiAqIEByZXR1cm5zIC0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGRlZmF1bHQgZXhwb3J0IG9mIHRoZSBtb2R1bGUuXG4gKi9cbmNvbnN0IGR5bmFtaWNJbXBvcnREZWZhdWx0ID0gYXN5bmMgPFQ+KHVybDogc3RyaW5nKTogUHJvbWlzZTxUPiA9PlxuICAoYXdhaXQgaW1wb3J0KC8qIHdlYnBhY2tJZ25vcmU6IHRydWUgKi8gdXJsKSkuZGVmYXVsdDtcblxuLyoqXG4gKiBUaGUgcHJveHkgd29ya2VyIGZhY3RvcnkgaW1wb3J0ZWQgZnJvbSB0aGUgcHJveHkgd29ya2VyIG1vZHVsZS5cbiAqXG4gKiBUaGlzIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gdGhlIFdlYkFzc2VtYmx5IHByb3h5IGlzIG5vdCBkaXNhYmxlZC5cbiAqL1xuY29uc3QgY3JlYXRlUHJveHlXb3JrZXI6ICgodXJsT3ZlcnJpZGU/OiBzdHJpbmcpID0+IFdvcmtlcikgfCB1bmRlZmluZWQgPVxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cywgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlc1xuICBCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSA/IHVuZGVmaW5lZCA6IHJlcXVpcmUoJy4vcHJveHktd29ya2VyL21haW4nKS5kZWZhdWx0O1xuXG4vKipcbiAqIEltcG9ydCB0aGUgcHJveHkgd29ya2VyLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBwZXJmb3JtIHRoZSBmb2xsb3dpbmcgc3RlcHM6XG4gKiAxLiBJZiBhIHByZWxvYWQgaXMgbmVlZGVkLCBpdCB3aWxsIHByZWxvYWQgdGhlIG1vZHVsZSBhbmQgcmV0dXJuIHRoZSBvYmplY3QgVVJMLlxuICogMi4gVXNlIHRoZSBwcm94eSB3b3JrZXIgZmFjdG9yeSB0byBjcmVhdGUgdGhlIHByb3h5IHdvcmtlci5cbiAqXG4gKiBAcmV0dXJucyAtIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgdHVwbGUgb2YgMiBlbGVtZW50czpcbiAqICAgICAgICAgICAgLSBUaGUgb2JqZWN0IFVSTCBvZiB0aGUgcHJlbG9hZGVkIG1vZHVsZSwgb3IgdW5kZWZpbmVkIGlmIG5vIHByZWxvYWQgaXMgbmVlZGVkLlxuICogICAgICAgICAgICAtIFRoZSBwcm94eSB3b3JrZXIuXG4gKi9cbmV4cG9ydCBjb25zdCBpbXBvcnRQcm94eVdvcmtlciA9IGFzeW5jICgpOiBQcm9taXNlPFt1bmRlZmluZWQgfCBzdHJpbmcsIFdvcmtlcl0+ID0+IHtcbiAgaWYgKCFzY3JpcHRTcmMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBsb2FkIHByb3h5IHdvcmtlcjogY2Fubm90IGRldGVybWluZSB0aGUgc2NyaXB0IHNvdXJjZSBVUkwuJyk7XG4gIH1cblxuICAvLyBJZiB0aGUgc2NyaXB0IHNvdXJjZSBpcyBmcm9tIHRoZSBzYW1lIG9yaWdpbiwgd2UgY2FuIHVzZSB0aGUgZW1iZWRkZWQgcHJveHkgbW9kdWxlIGRpcmVjdGx5LlxuICBpZiAoaXNTYW1lT3JpZ2luKHNjcmlwdFNyYykpIHtcbiAgICByZXR1cm4gW3VuZGVmaW5lZCwgY3JlYXRlUHJveHlXb3JrZXIhKCldO1xuICB9XG5cbiAgLy8gT3RoZXJ3aXNlLCBuZWVkIHRvIHByZWxvYWRcbiAgY29uc3QgdXJsID0gYXdhaXQgcHJlbG9hZChzY3JpcHRTcmMpO1xuICByZXR1cm4gW3VybCwgY3JlYXRlUHJveHlXb3JrZXIhKHVybCldO1xufTtcblxuLyoqXG4gKiBUaGUgZW1iZWRkZWQgV2ViQXNzZW1ibHkgbW9kdWxlLlxuICpcbiAqIFRoaXMgaXMgb25seSBhdmFpbGFibGUgaW4gRVNNIGFuZCB3aGVuIGVtYmVkZGluZyBpcyBub3QgZGlzYWJsZWQuXG4gKi9cbmNvbnN0IGVtYmVkZGVkV2FzbU1vZHVsZTogRW1zY3JpcHRlbk1vZHVsZUZhY3Rvcnk8T3J0V2FzbU1vZHVsZT4gfCB1bmRlZmluZWQgPVxuICBCVUlMRF9ERUZTLklTX0VTTSAmJiBCVUlMRF9ERUZTLkVOQUJMRV9CVU5ETEVfV0FTTV9KU1xuICAgID8gLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMsIEB0eXBlc2NyaXB0LWVzbGludC9uby12YXItcmVxdWlyZXNcbiAgICAgIHJlcXVpcmUoXG4gICAgICAgICFCVUlMRF9ERUZTLkRJU0FCTEVfSlNFUFxuICAgICAgICAgID8gJy4uLy4uL2Rpc3Qvb3J0LXdhc20tc2ltZC10aHJlYWRlZC5qc2VwLm1qcydcbiAgICAgICAgICA6ICcuLi8uLi9kaXN0L29ydC13YXNtLXNpbWQtdGhyZWFkZWQubWpzJyxcbiAgICAgICkuZGVmYXVsdFxuICAgIDogdW5kZWZpbmVkO1xuXG4vKipcbiAqIEltcG9ydCB0aGUgV2ViQXNzZW1ibHkgbW9kdWxlLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBwZXJmb3JtIHRoZSBmb2xsb3dpbmcgc3RlcHM6XG4gKiAxLiBJZiB0aGUgZW1iZWRkZWQgbW9kdWxlIGV4aXN0cyBhbmQgbm8gY3VzdG9tIFVSTCBpcyBzcGVjaWZpZWQsIHVzZSB0aGUgZW1iZWRkZWQgbW9kdWxlLlxuICogMi4gSWYgYSBwcmVsb2FkIGlzIG5lZWRlZCwgaXQgd2lsbCBwcmVsb2FkIHRoZSBtb2R1bGUgYW5kIHJldHVybiB0aGUgb2JqZWN0IFVSTC5cbiAqIDMuIE90aGVyd2lzZSwgaXQgd2lsbCBwZXJmb3JtIGEgZHluYW1pYyBpbXBvcnQgb2YgdGhlIG1vZHVsZS5cbiAqXG4gKiBAcmV0dXJucyAtIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgdHVwbGUgb2YgMiBlbGVtZW50czpcbiAqICAgICAgICAgICAgLSBUaGUgb2JqZWN0IFVSTCBvZiB0aGUgcHJlbG9hZGVkIG1vZHVsZSwgb3IgdW5kZWZpbmVkIGlmIG5vIHByZWxvYWQgaXMgbmVlZGVkLlxuICogICAgICAgICAgICAtIFRoZSBkZWZhdWx0IGV4cG9ydCBvZiB0aGUgbW9kdWxlLCB3aGljaCBpcyBhIGZhY3RvcnkgZnVuY3Rpb24gdG8gY3JlYXRlIHRoZSBXZWJBc3NlbWJseSBtb2R1bGUuXG4gKi9cbmV4cG9ydCBjb25zdCBpbXBvcnRXYXNtTW9kdWxlID0gYXN5bmMgKFxuICB1cmxPdmVycmlkZTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBwcmVmaXhPdmVycmlkZTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBpc011bHRpVGhyZWFkZWQ6IGJvb2xlYW4sXG4pOiBQcm9taXNlPFt1bmRlZmluZWQgfCBzdHJpbmcsIEVtc2NyaXB0ZW5Nb2R1bGVGYWN0b3J5PE9ydFdhc21Nb2R1bGU+XT4gPT4ge1xuICBpZiAoIXVybE92ZXJyaWRlICYmICFwcmVmaXhPdmVycmlkZSAmJiBlbWJlZGRlZFdhc21Nb2R1bGUgJiYgc2NyaXB0U3JjICYmIGlzU2FtZU9yaWdpbihzY3JpcHRTcmMpKSB7XG4gICAgcmV0dXJuIFt1bmRlZmluZWQsIGVtYmVkZGVkV2FzbU1vZHVsZV07XG4gIH0gZWxzZSB7XG4gICAgY29uc3Qgd2FzbU1vZHVsZUZpbGVuYW1lID0gIUJVSUxEX0RFRlMuRElTQUJMRV9KU0VQXG4gICAgICA/ICdvcnQtd2FzbS1zaW1kLXRocmVhZGVkLmpzZXAubWpzJ1xuICAgICAgOiAnb3J0LXdhc20tc2ltZC10aHJlYWRlZC5tanMnO1xuICAgIGNvbnN0IHdhc21Nb2R1bGVVcmwgPSB1cmxPdmVycmlkZSA/PyBub3JtYWxpemVVcmwod2FzbU1vZHVsZUZpbGVuYW1lLCBwcmVmaXhPdmVycmlkZSk7XG4gICAgLy8gbmVlZCB0byBwcmVsb2FkIGlmIGFsbCBvZiB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcbiAgICAvLyAxLiBub3QgaW4gTm9kZS5qcy5cbiAgICAvLyAgICAtIE5vZGUuanMgZG9lcyBub3QgaGF2ZSB0aGUgc2FtZSBvcmlnaW4gcG9saWN5IGZvciBjcmVhdGluZyB3b3JrZXJzLlxuICAgIC8vIDIuIG11bHRpLXRocmVhZGVkIGlzIGVuYWJsZWQuXG4gICAgLy8gICAgLSBJZiBtdWx0aS10aHJlYWRlZCBpcyBkaXNhYmxlZCwgbm8gd29ya2VyIHdpbGwgYmUgY3JlYXRlZC4gU28gd2UgZG9uJ3QgbmVlZCB0byBwcmVsb2FkIHRoZSBtb2R1bGUuXG4gICAgLy8gMy4gdGhlIGFic29sdXRlIFVSTCBpcyBhdmFpbGFibGUuXG4gICAgLy8gICAgLSBJZiB0aGUgYWJzb2x1dGUgVVJMIGlzIGZhaWxlZCB0byBiZSBjcmVhdGVkLCB0aGUgb3JpZ2luIGNhbm5vdCBiZSBkZXRlcm1pbmVkLiBJbiB0aGlzIGNhc2UsIHdlIHdpbGwgbm90XG4gICAgLy8gICAgcHJlbG9hZCB0aGUgbW9kdWxlLlxuICAgIC8vIDQuIHRoZSB3b3JrZXIgVVJMIGlzIG5vdCBmcm9tIHRoZSBzYW1lIG9yaWdpbi5cbiAgICAvLyAgICAtIElmIHRoZSB3b3JrZXIgVVJMIGlzIGZyb20gdGhlIHNhbWUgb3JpZ2luLCB3ZSBjYW4gY3JlYXRlIHRoZSB3b3JrZXIgZGlyZWN0bHkuXG4gICAgY29uc3QgbmVlZFByZWxvYWQgPSAhaXNOb2RlICYmIGlzTXVsdGlUaHJlYWRlZCAmJiB3YXNtTW9kdWxlVXJsICYmICFpc1NhbWVPcmlnaW4od2FzbU1vZHVsZVVybCwgcHJlZml4T3ZlcnJpZGUpO1xuICAgIGNvbnN0IHVybCA9IG5lZWRQcmVsb2FkXG4gICAgICA/IGF3YWl0IHByZWxvYWQod2FzbU1vZHVsZVVybClcbiAgICAgIDogKHdhc21Nb2R1bGVVcmwgPz8gZmFsbGJhY2tVcmwod2FzbU1vZHVsZUZpbGVuYW1lLCBwcmVmaXhPdmVycmlkZSkpO1xuICAgIHJldHVybiBbbmVlZFByZWxvYWQgPyB1cmwgOiB1bmRlZmluZWQsIGF3YWl0IGR5bmFtaWNJbXBvcnREZWZhdWx0PEVtc2NyaXB0ZW5Nb2R1bGVGYWN0b3J5PE9ydFdhc21Nb2R1bGU+Pih1cmwpXTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRW52IH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHR5cGUgeyBPcnRXYXNtTW9kdWxlIH0gZnJvbSAnLi93YXNtLXR5cGVzJztcbmltcG9ydCB7IGltcG9ydFdhc21Nb2R1bGUsIGluZmVyV2FzbVBhdGhQcmVmaXhGcm9tU2NyaXB0U3JjIH0gZnJvbSAnLi93YXNtLXV0aWxzLWltcG9ydCc7XG5cbmxldCB3YXNtOiBPcnRXYXNtTW9kdWxlIHwgdW5kZWZpbmVkO1xubGV0IGluaXRpYWxpemVkID0gZmFsc2U7XG5sZXQgaW5pdGlhbGl6aW5nID0gZmFsc2U7XG5sZXQgYWJvcnRlZCA9IGZhbHNlO1xuXG5jb25zdCBpc011bHRpVGhyZWFkU3VwcG9ydGVkID0gKCk6IGJvb2xlYW4gPT4ge1xuICAvLyBJZiAnU2hhcmVkQXJyYXlCdWZmZXInIGlzIG5vdCBhdmFpbGFibGUsIFdlYkFzc2VtYmx5IHRocmVhZHMgd2lsbCBub3Qgd29yay5cbiAgaWYgKHR5cGVvZiBTaGFyZWRBcnJheUJ1ZmZlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB0cnkge1xuICAgIC8vIFRlc3QgZm9yIHRyYW5zZmVyYWJpbGl0eSBvZiBTQUJzIChmb3IgYnJvd3NlcnMuIG5lZWRlZCBmb3IgRmlyZWZveClcbiAgICAvLyBodHRwczovL2dyb3Vwcy5nb29nbGUuY29tL2ZvcnVtLyMhbXNnL21vemlsbGEuZGV2LnBsYXRmb3JtL0lIa0JabEhFVHBBL2R3c01OY2hXRVFBSlxuICAgIGlmICh0eXBlb2YgTWVzc2FnZUNoYW5uZWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBuZXcgTWVzc2FnZUNoYW5uZWwoKS5wb3J0MS5wb3N0TWVzc2FnZShuZXcgU2hhcmVkQXJyYXlCdWZmZXIoMSkpO1xuICAgIH1cblxuICAgIC8vIFRlc3QgZm9yIFdlYkFzc2VtYmx5IHRocmVhZHMgY2FwYWJpbGl0eSAoZm9yIGJvdGggYnJvd3NlcnMgYW5kIE5vZGUuanMpXG4gICAgLy8gVGhpcyB0eXBlZCBhcnJheSBpcyBhIFdlYkFzc2VtYmx5IHByb2dyYW0gY29udGFpbmluZyB0aHJlYWRlZCBpbnN0cnVjdGlvbnMuXG4gICAgcmV0dXJuIFdlYkFzc2VtYmx5LnZhbGlkYXRlKFxuICAgICAgbmV3IFVpbnQ4QXJyYXkoW1xuICAgICAgICAwLCA5NywgMTE1LCAxMDksIDEsIDAsIDAsIDAsIDEsIDQsIDEsIDk2LCAwLCAwLCAzLCAyLCAxLCAwLCA1LCA0LCAxLCAzLCAxLCAxLCAxMCwgMTEsIDEsIDksIDAsIDY1LCAwLCAyNTQsIDE2LFxuICAgICAgICAyLCAwLCAyNiwgMTEsXG4gICAgICBdKSxcbiAgICApO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59O1xuXG5jb25zdCBpc1NpbWRTdXBwb3J0ZWQgPSAoKTogYm9vbGVhbiA9PiB7XG4gIHRyeSB7XG4gICAgLy8gVGVzdCBmb3IgV2ViQXNzZW1ibHkgU0lNRCBjYXBhYmlsaXR5IChmb3IgYm90aCBicm93c2VycyBhbmQgTm9kZS5qcylcbiAgICAvLyBUaGlzIHR5cGVkIGFycmF5IGlzIGEgV2ViQXNzZW1ibHkgcHJvZ3JhbSBjb250YWluaW5nIFNJTUQgaW5zdHJ1Y3Rpb25zLlxuXG4gICAgLy8gVGhlIGJpbmFyeSBkYXRhIGlzIGdlbmVyYXRlZCBmcm9tIHRoZSBmb2xsb3dpbmcgY29kZSBieSB3YXQyd2FzbTpcbiAgICAvL1xuICAgIC8vIChtb2R1bGVcbiAgICAvLyAgICh0eXBlICR0MCAoZnVuYykpXG4gICAgLy8gICAoZnVuYyAkZjAgKHR5cGUgJHQwKVxuICAgIC8vICAgICAoZHJvcFxuICAgIC8vICAgICAgIChpMzJ4NC5kb3RfaTE2eDhfc1xuICAgIC8vICAgICAgICAgKGk4eDE2LnNwbGF0XG4gICAgLy8gICAgICAgICAgIChpMzIuY29uc3QgMCkpXG4gICAgLy8gICAgICAgICAodjEyOC5jb25zdCBpMzJ4NCAweDAwMDAwMDAwIDB4MDAwMDAwMDAgMHgwMDAwMDAwMCAweDAwMDAwMDAwKSkpKSlcblxuICAgIHJldHVybiBXZWJBc3NlbWJseS52YWxpZGF0ZShcbiAgICAgIG5ldyBVaW50OEFycmF5KFtcbiAgICAgICAgMCwgOTcsIDExNSwgMTA5LCAxLCAwLCAwLCAwLCAxLCA0LCAxLCA5NiwgMCwgMCwgMywgMiwgMSwgMCwgMTAsIDMwLCAxLCAyOCwgMCwgNjUsIDAsIDI1MywgMTUsIDI1MywgMTIsIDAsIDAsIDAsXG4gICAgICAgIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDI1MywgMTg2LCAxLCAyNiwgMTEsXG4gICAgICBdKSxcbiAgICApO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59O1xuXG5jb25zdCBpc1JlbGF4ZWRTaW1kU3VwcG9ydGVkID0gKCk6IGJvb2xlYW4gPT4ge1xuICB0cnkge1xuICAgIC8vIFRlc3QgZm9yIFdlYkFzc2VtYmx5IFJlbGF4ZWQgU0lNRCBjYXBhYmlsaXR5IChmb3IgYm90aCBicm93c2VycyBhbmQgTm9kZS5qcylcbiAgICAvLyBUaGlzIHR5cGVkIGFycmF5IGlzIGEgV2ViQXNzZW1ibHkgcHJvZ3JhbSBjb250YWluaW5nIFJlbGF4ZWQgU0lNRCBpbnN0cnVjdGlvbnMuXG5cbiAgICAvLyBUaGUgYmluYXJ5IGRhdGEgaXMgZ2VuZXJhdGVkIGZyb20gdGhlIGZvbGxvd2luZyBjb2RlIGJ5IHdhdDJ3YXNtOlxuICAgIC8vIChtb2R1bGVcbiAgICAvLyAgIChmdW5jIChyZXN1bHQgdjEyOClcbiAgICAvLyAgICAgIGkzMi5jb25zdCAxXG4gICAgLy8gICAgICBpOHgxNi5zcGxhdFxuICAgIC8vICAgICAgaTMyLmNvbnN0IDJcbiAgICAvLyAgICAgIGk4eDE2LnNwbGF0XG4gICAgLy8gICAgICBpMzIuY29uc3QgM1xuICAgIC8vICAgICAgaTh4MTYuc3BsYXRcbiAgICAvLyAgICAgIGkzMng0LnJlbGF4ZWRfZG90X2k4eDE2X2k3eDE2X2FkZF9zXG4gICAgLy8gICApXG4gICAgLy8gIClcbiAgICByZXR1cm4gV2ViQXNzZW1ibHkudmFsaWRhdGUoXG4gICAgICBuZXcgVWludDhBcnJheShbXG4gICAgICAgIDAsIDk3LCAxMTUsIDEwOSwgMSwgMCwgMCwgMCwgMSwgNSwgMSwgOTYsIDAsIDEsIDEyMywgMywgMiwgMSwgMCwgMTAsIDE5LCAxLCAxNywgMCwgNjUsIDEsIDI1MywgMTUsIDY1LCAyLCAyNTMsXG4gICAgICAgIDE1LCA2NSwgMywgMjUzLCAxNSwgMjUzLCAxNDcsIDIsIDExLFxuICAgICAgXSksXG4gICAgKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGluaXRpYWxpemVXZWJBc3NlbWJseSA9IGFzeW5jIChmbGFnczogRW52LldlYkFzc2VtYmx5RmxhZ3MpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgaWYgKGluaXRpYWxpemVkKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG4gIGlmIChpbml0aWFsaXppbmcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJtdWx0aXBsZSBjYWxscyB0byAnaW5pdGlhbGl6ZVdlYkFzc2VtYmx5KCknIGRldGVjdGVkLlwiKTtcbiAgfVxuICBpZiAoYWJvcnRlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcInByZXZpb3VzIGNhbGwgdG8gJ2luaXRpYWxpemVXZWJBc3NlbWJseSgpJyBmYWlsZWQuXCIpO1xuICB9XG5cbiAgaW5pdGlhbGl6aW5nID0gdHJ1ZTtcblxuICAvLyB3YXNtIGZsYWdzIGFyZSBhbHJlYWR5IGluaXRpYWxpemVkXG4gIGNvbnN0IHRpbWVvdXQgPSBmbGFncy5pbml0VGltZW91dCE7XG4gIGxldCBudW1UaHJlYWRzID0gZmxhZ3MubnVtVGhyZWFkcyE7XG5cbiAgLy8gZW5zdXJlIFNJTUQgaXMgc3VwcG9ydGVkXG4gIGlmIChmbGFncy5zaW1kID09PSBmYWxzZSkge1xuICAgIC8vIHNraXAgU0lNRCBmZWF0dXJlIGNoZWNraW5nIGFzIGl0IGlzIGRpc2FibGVkIGV4cGxpY2l0bHkgYnkgdXNlclxuICB9IGVsc2UgaWYgKGZsYWdzLnNpbWQgPT09ICdyZWxheGVkJykge1xuICAgIC8vIGNoZWNrIGlmIHJlbGF4ZWQgU0lNRCBpcyBzdXBwb3J0ZWRcbiAgICBpZiAoIWlzUmVsYXhlZFNpbWRTdXBwb3J0ZWQoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZWxheGVkIFdlYkFzc2VtYmx5IFNJTUQgaXMgbm90IHN1cHBvcnRlZCBpbiB0aGUgY3VycmVudCBlbnZpcm9ubWVudC4nKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoIWlzU2ltZFN1cHBvcnRlZCgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdXZWJBc3NlbWJseSBTSU1EIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuJyk7XG4gIH1cblxuICAvLyBjaGVjayBpZiBtdWx0aS10aHJlYWRpbmcgaXMgc3VwcG9ydGVkXG4gIGNvbnN0IG11bHRpVGhyZWFkU3VwcG9ydGVkID0gaXNNdWx0aVRocmVhZFN1cHBvcnRlZCgpO1xuICBpZiAobnVtVGhyZWFkcyA+IDEgJiYgIW11bHRpVGhyZWFkU3VwcG9ydGVkKSB7XG4gICAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyAmJiAhc2VsZi5jcm9zc09yaWdpbklzb2xhdGVkKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAnZW52Lndhc20ubnVtVGhyZWFkcyBpcyBzZXQgdG8gJyArXG4gICAgICAgICAgbnVtVGhyZWFkcyArXG4gICAgICAgICAgJywgYnV0IHRoaXMgd2lsbCBub3Qgd29yayB1bmxlc3MgeW91IGVuYWJsZSBjcm9zc09yaWdpbklzb2xhdGVkIG1vZGUuICcgK1xuICAgICAgICAgICdTZWUgaHR0cHM6Ly93ZWIuZGV2L2Nyb3NzLW9yaWdpbi1pc29sYXRpb24tZ3VpZGUvIGZvciBtb3JlIGluZm8uJyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICBjb25zb2xlLndhcm4oXG4gICAgICAnV2ViQXNzZW1ibHkgbXVsdGktdGhyZWFkaW5nIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuICcgKyAnRmFsbGluZyBiYWNrIHRvIHNpbmdsZS10aHJlYWRpbmcuJyxcbiAgICApO1xuXG4gICAgLy8gc2V0IGZsYWdzLm51bVRocmVhZHMgdG8gMSBzbyB0aGF0IE9ydEluaXQoKSB3aWxsIG5vdCBjcmVhdGUgYSBnbG9iYWwgdGhyZWFkIHBvb2wuXG4gICAgZmxhZ3MubnVtVGhyZWFkcyA9IG51bVRocmVhZHMgPSAxO1xuICB9XG5cbiAgY29uc3Qgd2FzbVBhdGhzID0gZmxhZ3Mud2FzbVBhdGhzO1xuICBjb25zdCB3YXNtUHJlZml4T3ZlcnJpZGUgPSB0eXBlb2Ygd2FzbVBhdGhzID09PSAnc3RyaW5nJyA/IHdhc21QYXRocyA6IHVuZGVmaW5lZDtcbiAgY29uc3QgbWpzUGF0aE92ZXJyaWRlRmxhZyA9ICh3YXNtUGF0aHMgYXMgRW52Lldhc21GaWxlUGF0aHMpPy5tanM7XG4gIGNvbnN0IG1qc1BhdGhPdmVycmlkZSA9IChtanNQYXRoT3ZlcnJpZGVGbGFnIGFzIFVSTCk/LmhyZWYgPz8gbWpzUGF0aE92ZXJyaWRlRmxhZztcbiAgY29uc3Qgd2FzbVBhdGhPdmVycmlkZUZsYWcgPSAod2FzbVBhdGhzIGFzIEVudi5XYXNtRmlsZVBhdGhzKT8ud2FzbTtcbiAgY29uc3Qgd2FzbVBhdGhPdmVycmlkZSA9ICh3YXNtUGF0aE92ZXJyaWRlRmxhZyBhcyBVUkwpPy5ocmVmID8/IHdhc21QYXRoT3ZlcnJpZGVGbGFnO1xuICBjb25zdCB3YXNtQmluYXJ5T3ZlcnJpZGUgPSBmbGFncy53YXNtQmluYXJ5O1xuXG4gIGNvbnN0IFtvYmplY3RVcmwsIG9ydFdhc21GYWN0b3J5XSA9IGF3YWl0IGltcG9ydFdhc21Nb2R1bGUobWpzUGF0aE92ZXJyaWRlLCB3YXNtUHJlZml4T3ZlcnJpZGUsIG51bVRocmVhZHMgPiAxKTtcblxuICBsZXQgaXNUaW1lb3V0ID0gZmFsc2U7XG5cbiAgY29uc3QgdGFza3M6IEFycmF5PFByb21pc2U8dm9pZD4+ID0gW107XG5cbiAgLy8gcHJvbWlzZSBmb3IgdGltZW91dFxuICBpZiAodGltZW91dCA+IDApIHtcbiAgICB0YXNrcy5wdXNoKFxuICAgICAgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgaXNUaW1lb3V0ID0gdHJ1ZTtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0sIHRpbWVvdXQpO1xuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIC8vIHByb21pc2UgZm9yIG1vZHVsZSBpbml0aWFsaXphdGlvblxuICB0YXNrcy5wdXNoKFxuICAgIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IGNvbmZpZzogUGFydGlhbDxPcnRXYXNtTW9kdWxlPiA9IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBudW1iZXIgb2YgdGhyZWFkcy4gV2ViQXNzZW1ibHkgd2lsbCBjcmVhdGUgKE1vZHVsZS5udW1UaHJlYWRzIC0gMSkgd29ya2Vycy4gSWYgaXQgaXMgMSwgbm8gd29ya2VyIHdpbGwgYmVcbiAgICAgICAgICogY3JlYXRlZC5cbiAgICAgICAgICovXG4gICAgICAgIG51bVRocmVhZHMsXG4gICAgICB9O1xuXG4gICAgICBpZiAod2FzbUJpbmFyeU92ZXJyaWRlKSB7XG4gICAgICAgIC8vIFNldCBhIGN1c3RvbSBidWZmZXIgd2hpY2ggY29udGFpbnMgdGhlIFdlYkFzc2VtYmx5IGJpbmFyeS4gVGhpcyB3aWxsIHNraXAgdGhlIHdhc20gZmlsZSBmZXRjaGluZy5cbiAgICAgICAgY29uZmlnLndhc21CaW5hcnkgPSB3YXNtQmluYXJ5T3ZlcnJpZGU7XG4gICAgICB9IGVsc2UgaWYgKHdhc21QYXRoT3ZlcnJpZGUgfHwgd2FzbVByZWZpeE92ZXJyaWRlKSB7XG4gICAgICAgIC8vIEEgY2FsbGJhY2sgZnVuY3Rpb24gdG8gbG9jYXRlIHRoZSBXZWJBc3NlbWJseSBmaWxlLiBUaGUgZnVuY3Rpb24gc2hvdWxkIHJldHVybiB0aGUgZnVsbCBwYXRoIG9mIHRoZSBmaWxlLlxuICAgICAgICAvL1xuICAgICAgICAvLyBTaW5jZSBFbXNjcmlwdGVuIDMuMS41OCwgdGhpcyBmdW5jdGlvbiBpcyBvbmx5IGNhbGxlZCBmb3IgdGhlIC53YXNtIGZpbGUuXG4gICAgICAgIGNvbmZpZy5sb2NhdGVGaWxlID0gKGZpbGVOYW1lKSA9PiB3YXNtUGF0aE92ZXJyaWRlID8/IHdhc21QcmVmaXhPdmVycmlkZSArIGZpbGVOYW1lO1xuICAgICAgfSBlbHNlIGlmIChtanNQYXRoT3ZlcnJpZGUgJiYgbWpzUGF0aE92ZXJyaWRlLmluZGV4T2YoJ2Jsb2I6JykgIT09IDApIHtcbiAgICAgICAgLy8gaWYgbWpzIHBhdGggaXMgc3BlY2lmaWVkLCB1c2UgaXQgYXMgdGhlIGJhc2UgcGF0aCBmb3IgdGhlIC53YXNtIGZpbGUuXG4gICAgICAgIGNvbmZpZy5sb2NhdGVGaWxlID0gKGZpbGVOYW1lKSA9PiBuZXcgVVJMKGZpbGVOYW1lLCBtanNQYXRoT3ZlcnJpZGUpLmhyZWY7XG4gICAgICB9IGVsc2UgaWYgKG9iamVjdFVybCkge1xuICAgICAgICBjb25zdCBpbmZlcnJlZFdhc21QYXRoUHJlZml4ID0gaW5mZXJXYXNtUGF0aFByZWZpeEZyb21TY3JpcHRTcmMoKTtcbiAgICAgICAgaWYgKGluZmVycmVkV2FzbVBhdGhQcmVmaXgpIHtcbiAgICAgICAgICAvLyBpZiB0aGUgd2FzbSBtb2R1bGUgaXMgcHJlbG9hZGVkLCB1c2UgdGhlIGluZmVycmVkIHdhc20gcGF0aCBhcyB0aGUgYmFzZSBwYXRoIGZvciB0aGUgLndhc20gZmlsZS5cbiAgICAgICAgICBjb25maWcubG9jYXRlRmlsZSA9IChmaWxlTmFtZSkgPT4gaW5mZXJyZWRXYXNtUGF0aFByZWZpeCArIGZpbGVOYW1lO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIG9ydFdhc21GYWN0b3J5KGNvbmZpZykudGhlbihcbiAgICAgICAgLy8gd2FzbSBtb2R1bGUgaW5pdGlhbGl6ZWQgc3VjY2Vzc2Z1bGx5XG4gICAgICAgIChtb2R1bGUpID0+IHtcbiAgICAgICAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcbiAgICAgICAgICBpbml0aWFsaXplZCA9IHRydWU7XG4gICAgICAgICAgd2FzbSA9IG1vZHVsZTtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgaWYgKG9iamVjdFVybCkge1xuICAgICAgICAgICAgVVJMLnJldm9rZU9iamVjdFVSTChvYmplY3RVcmwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgLy8gd2FzbSBtb2R1bGUgZmFpbGVkIHRvIGluaXRpYWxpemVcbiAgICAgICAgKHdoYXQpID0+IHtcbiAgICAgICAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcbiAgICAgICAgICBhYm9ydGVkID0gdHJ1ZTtcbiAgICAgICAgICByZWplY3Qod2hhdCk7XG4gICAgICAgIH0sXG4gICAgICApO1xuICAgIH0pLFxuICApO1xuXG4gIGF3YWl0IFByb21pc2UucmFjZSh0YXNrcyk7XG5cbiAgaWYgKGlzVGltZW91dCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgV2ViQXNzZW1ibHkgYmFja2VuZCBpbml0aWFsaXppbmcgZmFpbGVkIGR1ZSB0byB0aW1lb3V0OiAke3RpbWVvdXR9bXNgKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGdldEluc3RhbmNlID0gKCk6IE9ydFdhc21Nb2R1bGUgPT4ge1xuICBpZiAoaW5pdGlhbGl6ZWQgJiYgd2FzbSkge1xuICAgIHJldHVybiB3YXNtO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdXZWJBc3NlbWJseSBpcyBub3QgaW5pdGlhbGl6ZWQgeWV0LicpO1xufTtcblxuZXhwb3J0IGNvbnN0IGRpc3Bvc2UgPSAoKTogdm9pZCA9PiB7XG4gIGlmIChpbml0aWFsaXplZCAmJiAhaW5pdGlhbGl6aW5nICYmICFhYm9ydGVkKSB7XG4gICAgLy8gVE9ETzogY3VycmVudGx5IFwiUFRocmVhZC50ZXJtaW5hdGVBbGxUaHJlYWRzKClcIiBpcyBub3QgZXhwb3NlZCBpbiB0aGUgd2FzbSBtb2R1bGUuXG4gICAgLy8gICAgICAgQW5kIHRoaXMgZnVuY3Rpb24gaXMgbm90IHlldCBjYWxsZWQgYnkgYW55IGNvZGUuXG4gICAgLy8gICAgICAgSWYgaXQgaXMgbmVlZGVkIGluIHRoZSBmdXR1cmUsIHdlIHNob3VsZCBleHBvc2UgaXQgaW4gdGhlIHdhc20gbW9kdWxlIGFuZCB1bmNvbW1lbnQgdGhlIGZvbGxvd2luZyBsaW5lLlxuXG4gICAgLy8gd2FzbT8uUFRocmVhZD8udGVybWluYXRlQWxsVGhyZWFkcygpO1xuICAgIHdhc20gPSB1bmRlZmluZWQ7XG5cbiAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcbiAgICBpbml0aWFsaXplZCA9IGZhbHNlO1xuICAgIGFib3J0ZWQgPSB0cnVlO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBnZXRJbnN0YW5jZSB9IGZyb20gJy4vd2FzbS1mYWN0b3J5JztcblxuZXhwb3J0IGNvbnN0IGFsbG9jV2FzbVN0cmluZyA9IChkYXRhOiBzdHJpbmcsIGFsbG9jczogbnVtYmVyW10pOiBudW1iZXIgPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcblxuICBjb25zdCBkYXRhTGVuZ3RoID0gd2FzbS5sZW5ndGhCeXRlc1VURjgoZGF0YSkgKyAxO1xuICBjb25zdCBkYXRhT2Zmc2V0ID0gd2FzbS5fbWFsbG9jKGRhdGFMZW5ndGgpO1xuICB3YXNtLnN0cmluZ1RvVVRGOChkYXRhLCBkYXRhT2Zmc2V0LCBkYXRhTGVuZ3RoKTtcbiAgYWxsb2NzLnB1c2goZGF0YU9mZnNldCk7XG5cbiAgcmV0dXJuIGRhdGFPZmZzZXQ7XG59O1xuXG5pbnRlcmZhY2UgRXh0cmFPcHRpb25zSGFuZGxlciB7XG4gIChuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpOiB2b2lkO1xufVxuXG5leHBvcnQgY29uc3QgaXRlcmF0ZUV4dHJhT3B0aW9ucyA9IChcbiAgb3B0aW9uczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIHByZWZpeDogc3RyaW5nLFxuICBzZWVuOiBXZWFrU2V0PFJlY29yZDxzdHJpbmcsIHVua25vd24+PixcbiAgaGFuZGxlcjogRXh0cmFPcHRpb25zSGFuZGxlcixcbik6IHZvaWQgPT4ge1xuICBpZiAodHlwZW9mIG9wdGlvbnMgPT0gJ29iamVjdCcgJiYgb3B0aW9ucyAhPT0gbnVsbCkge1xuICAgIGlmIChzZWVuLmhhcyhvcHRpb25zKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaXJjdWxhciByZWZlcmVuY2UgaW4gb3B0aW9ucycpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZWVuLmFkZChvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICBPYmplY3QuZW50cmllcyhvcHRpb25zKS5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICBjb25zdCBuYW1lID0gcHJlZml4ID8gcHJlZml4ICsga2V5IDoga2V5O1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICBpdGVyYXRlRXh0cmFPcHRpb25zKHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBuYW1lICsgJy4nLCBzZWVuLCBoYW5kbGVyKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgaGFuZGxlcihuYW1lLCB2YWx1ZS50b1N0cmluZygpKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICBoYW5kbGVyKG5hbWUsIHZhbHVlID8gJzEnIDogJzAnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4ndCBoYW5kbGUgZXh0cmEgY29uZmlnIHR5cGU6ICR7dHlwZW9mIHZhbHVlfWApO1xuICAgIH1cbiAgfSk7XG59O1xuXG4vKipcbiAqIGNoZWNrIHdlYiBhc3NlbWJseSBBUEkncyBsYXN0IGVycm9yIGFuZCB0aHJvdyBlcnJvciBpZiBhbnkgZXJyb3Igb2NjdXJyZWQuXG4gKiBAcGFyYW0gbWVzc2FnZSBhIG1lc3NhZ2UgdXNlZCB3aGVuIGFuIGVycm9yIG9jY3VycmVkLlxuICovXG5leHBvcnQgY29uc3QgY2hlY2tMYXN0RXJyb3IgPSAobWVzc2FnZTogc3RyaW5nKTogdm9pZCA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuXG4gIGNvbnN0IHN0YWNrID0gd2FzbS5zdGFja1NhdmUoKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBwdHJTaXplID0gd2FzbS5QVFJfU0laRTtcbiAgICBjb25zdCBwYXJhbXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2MoMiAqIHB0clNpemUpO1xuICAgIHdhc20uX09ydEdldExhc3RFcnJvcihwYXJhbXNPZmZzZXQsIHBhcmFtc09mZnNldCArIHB0clNpemUpO1xuICAgIGNvbnN0IGVycm9yQ29kZSA9IE51bWJlcih3YXNtLmdldFZhbHVlKHBhcmFtc09mZnNldCwgcHRyU2l6ZSA9PT0gNCA/ICdpMzInIDogJ2k2NCcpKTtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2VQb2ludGVyID0gd2FzbS5nZXRWYWx1ZShwYXJhbXNPZmZzZXQgKyBwdHJTaXplLCAnKicpO1xuICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yTWVzc2FnZVBvaW50ZXIgPyB3YXNtLlVURjhUb1N0cmluZyhlcnJvck1lc3NhZ2VQb2ludGVyKSA6ICcnO1xuICAgIHRocm93IG5ldyBFcnJvcihgJHttZXNzYWdlfSBFUlJPUl9DT0RFOiAke2Vycm9yQ29kZX0sIEVSUk9SX01FU1NBR0U6ICR7ZXJyb3JNZXNzYWdlfWApO1xuICB9IGZpbmFsbHkge1xuICAgIHdhc20uc3RhY2tSZXN0b3JlKHN0YWNrKTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgSW5mZXJlbmNlU2Vzc2lvbiB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IGdldEluc3RhbmNlIH0gZnJvbSAnLi93YXNtLWZhY3RvcnknO1xuaW1wb3J0IHsgYWxsb2NXYXNtU3RyaW5nLCBjaGVja0xhc3RFcnJvciwgaXRlcmF0ZUV4dHJhT3B0aW9ucyB9IGZyb20gJy4vd2FzbS11dGlscyc7XG5cbmV4cG9ydCBjb25zdCBzZXRSdW5PcHRpb25zID0gKG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uUnVuT3B0aW9ucyk6IFtudW1iZXIsIG51bWJlcltdXSA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICBsZXQgcnVuT3B0aW9uc0hhbmRsZSA9IDA7XG4gIGNvbnN0IGFsbG9jczogbnVtYmVyW10gPSBbXTtcblxuICBjb25zdCBydW5PcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIHRyeSB7XG4gICAgaWYgKG9wdGlvbnM/LmxvZ1NldmVyaXR5TGV2ZWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcnVuT3B0aW9ucy5sb2dTZXZlcml0eUxldmVsID0gMjsgLy8gRGVmYXVsdCB0byB3YXJuaW5nXG4gICAgfSBlbHNlIGlmIChcbiAgICAgIHR5cGVvZiBvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwgIT09ICdudW1iZXInIHx8XG4gICAgICAhTnVtYmVyLmlzSW50ZWdlcihvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwpIHx8XG4gICAgICBvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwgPCAwIHx8XG4gICAgICBvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwgPiA0XG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGxvZyBzZXJ2ZXJpdHkgbGV2ZWwgaXMgbm90IHZhbGlkOiAke29wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbH1gKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucz8ubG9nVmVyYm9zaXR5TGV2ZWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcnVuT3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCA9IDA7IC8vIERlZmF1bHQgdG8gMFxuICAgIH0gZWxzZSBpZiAodHlwZW9mIG9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwgIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKG9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGxvZyB2ZXJib3NpdHkgbGV2ZWwgaXMgbm90IHZhbGlkOiAke29wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWx9YCk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnM/LnRlcm1pbmF0ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBydW5PcHRpb25zLnRlcm1pbmF0ZSA9IGZhbHNlO1xuICAgIH1cblxuICAgIGxldCB0YWdEYXRhT2Zmc2V0ID0gMDtcbiAgICBpZiAob3B0aW9ucz8udGFnICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRhZ0RhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcob3B0aW9ucy50YWcsIGFsbG9jcyk7XG4gICAgfVxuXG4gICAgcnVuT3B0aW9uc0hhbmRsZSA9IHdhc20uX09ydENyZWF0ZVJ1bk9wdGlvbnMoXG4gICAgICBydW5PcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwhLFxuICAgICAgcnVuT3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCEsXG4gICAgICAhIXJ1bk9wdGlvbnMudGVybWluYXRlISxcbiAgICAgIHRhZ0RhdGFPZmZzZXQsXG4gICAgKTtcbiAgICBpZiAocnVuT3B0aW9uc0hhbmRsZSA9PT0gMCkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBjcmVhdGUgcnVuIG9wdGlvbnMuXCIpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy5leHRyYSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpdGVyYXRlRXh0cmFPcHRpb25zKG9wdGlvbnMuZXh0cmEsICcnLCBuZXcgV2Vha1NldDxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oKSwgKGtleSwgdmFsdWUpID0+IHtcbiAgICAgICAgY29uc3Qga2V5RGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyhrZXksIGFsbG9jcyk7XG4gICAgICAgIGNvbnN0IHZhbHVlRGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyh2YWx1ZSwgYWxsb2NzKTtcblxuICAgICAgICBpZiAod2FzbS5fT3J0QWRkUnVuQ29uZmlnRW50cnkocnVuT3B0aW9uc0hhbmRsZSwga2V5RGF0YU9mZnNldCwgdmFsdWVEYXRhT2Zmc2V0KSAhPT0gMCkge1xuICAgICAgICAgIGNoZWNrTGFzdEVycm9yKGBDYW4ndCBzZXQgYSBydW4gY29uZmlnIGVudHJ5OiAke2tleX0gLSAke3ZhbHVlfS5gKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFtydW5PcHRpb25zSGFuZGxlLCBhbGxvY3NdO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKHJ1bk9wdGlvbnNIYW5kbGUgIT09IDApIHtcbiAgICAgIHdhc20uX09ydFJlbGVhc2VSdW5PcHRpb25zKHJ1bk9wdGlvbnNIYW5kbGUpO1xuICAgIH1cbiAgICBhbGxvY3MuZm9yRWFjaCgoYWxsb2MpID0+IHdhc20uX2ZyZWUoYWxsb2MpKTtcbiAgICB0aHJvdyBlO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgdHlwZSB7IEluZmVyZW5jZVNlc3Npb24gfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBnZXRJbnN0YW5jZSB9IGZyb20gJy4vd2FzbS1mYWN0b3J5JztcbmltcG9ydCB7IGFsbG9jV2FzbVN0cmluZywgY2hlY2tMYXN0RXJyb3IsIGl0ZXJhdGVFeHRyYU9wdGlvbnMgfSBmcm9tICcuL3dhc20tdXRpbHMnO1xuXG5jb25zdCBnZXRHcmFwaE9wdGltemF0aW9uTGV2ZWwgPSAoZ3JhcGhPcHRpbWl6YXRpb25MZXZlbDogc3RyaW5nIHwgdW5rbm93bik6IG51bWJlciA9PiB7XG4gIHN3aXRjaCAoZ3JhcGhPcHRpbWl6YXRpb25MZXZlbCkge1xuICAgIGNhc2UgJ2Rpc2FibGVkJzpcbiAgICAgIHJldHVybiAwO1xuICAgIGNhc2UgJ2Jhc2ljJzpcbiAgICAgIHJldHVybiAxO1xuICAgIGNhc2UgJ2V4dGVuZGVkJzpcbiAgICAgIHJldHVybiAyO1xuICAgIGNhc2UgJ2FsbCc6XG4gICAgICByZXR1cm4gOTk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZ3JhcGggb3B0aW1pemF0aW9uIGxldmVsOiAke2dyYXBoT3B0aW1pemF0aW9uTGV2ZWx9YCk7XG4gIH1cbn07XG5cbmNvbnN0IGdldEV4ZWN1dGlvbk1vZGUgPSAoZXhlY3V0aW9uTW9kZTogJ3NlcXVlbnRpYWwnIHwgJ3BhcmFsbGVsJyk6IG51bWJlciA9PiB7XG4gIHN3aXRjaCAoZXhlY3V0aW9uTW9kZSkge1xuICAgIGNhc2UgJ3NlcXVlbnRpYWwnOlxuICAgICAgcmV0dXJuIDA7XG4gICAgY2FzZSAncGFyYWxsZWwnOlxuICAgICAgcmV0dXJuIDE7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZXhlY3V0aW9uIG1vZGU6ICR7ZXhlY3V0aW9uTW9kZX1gKTtcbiAgfVxufTtcblxuY29uc3QgYXBwZW5kRGVmYXVsdE9wdGlvbnMgPSAob3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6IHZvaWQgPT4ge1xuICBpZiAoIW9wdGlvbnMuZXh0cmEpIHtcbiAgICBvcHRpb25zLmV4dHJhID0ge307XG4gIH1cbiAgaWYgKCFvcHRpb25zLmV4dHJhLnNlc3Npb24pIHtcbiAgICBvcHRpb25zLmV4dHJhLnNlc3Npb24gPSB7fTtcbiAgfVxuICBjb25zdCBzZXNzaW9uID0gb3B0aW9ucy5leHRyYS5zZXNzaW9uIGFzIFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIGlmICghc2Vzc2lvbi51c2Vfb3J0X21vZGVsX2J5dGVzX2RpcmVjdGx5KSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNhbWVsY2FzZVxuICAgIHNlc3Npb24udXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseSA9ICcxJztcbiAgfVxuXG4gIC8vIGlmIHVzaW5nIEpTRVAgd2l0aCBXZWJHUFUsIGFsd2F5cyBkaXNhYmxlIG1lbW9yeSBwYXR0ZXJuXG4gIGlmIChcbiAgICBvcHRpb25zLmV4ZWN1dGlvblByb3ZpZGVycyAmJlxuICAgIG9wdGlvbnMuZXhlY3V0aW9uUHJvdmlkZXJzLnNvbWUoKGVwKSA9PiAodHlwZW9mIGVwID09PSAnc3RyaW5nJyA/IGVwIDogZXAubmFtZSkgPT09ICd3ZWJncHUnKVxuICApIHtcbiAgICBvcHRpb25zLmVuYWJsZU1lbVBhdHRlcm4gPSBmYWxzZTtcbiAgfVxufTtcblxuY29uc3QgYXBwZW5kU2Vzc2lvbkNvbmZpZyA9IChzZXNzaW9uT3B0aW9uc0hhbmRsZTogbnVtYmVyLCBrZXk6IHN0cmluZywgdmFsdWU6IHN0cmluZywgYWxsb2NzOiBudW1iZXJbXSk6IHZvaWQgPT4ge1xuICBjb25zdCBrZXlEYXRhT2Zmc2V0ID0gYWxsb2NXYXNtU3RyaW5nKGtleSwgYWxsb2NzKTtcbiAgY29uc3QgdmFsdWVEYXRhT2Zmc2V0ID0gYWxsb2NXYXNtU3RyaW5nKHZhbHVlLCBhbGxvY3MpO1xuICBpZiAoZ2V0SW5zdGFuY2UoKS5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5KHNlc3Npb25PcHRpb25zSGFuZGxlLCBrZXlEYXRhT2Zmc2V0LCB2YWx1ZURhdGFPZmZzZXQpICE9PSAwKSB7XG4gICAgY2hlY2tMYXN0RXJyb3IoYENhbid0IHNldCBhIHNlc3Npb24gY29uZmlnIGVudHJ5OiAke2tleX0gLSAke3ZhbHVlfS5gKTtcbiAgfVxufTtcblxuY29uc3QgYXBwZW5kRXBPcHRpb24gPSAoZXBPcHRpb25zOiBBcnJheTxbbnVtYmVyLCBudW1iZXJdPiwga2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcsIGFsbG9jczogbnVtYmVyW10pOiB2b2lkID0+IHtcbiAgY29uc3Qga2V5RGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyhrZXksIGFsbG9jcyk7XG4gIGNvbnN0IHZhbHVlRGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyh2YWx1ZSwgYWxsb2NzKTtcbiAgZXBPcHRpb25zLnB1c2goW2tleURhdGFPZmZzZXQsIHZhbHVlRGF0YU9mZnNldF0pO1xufTtcblxuY29uc3Qgc2V0RXhlY3V0aW9uUHJvdmlkZXJzID0gYXN5bmMgKFxuICBzZXNzaW9uT3B0aW9uc0hhbmRsZTogbnVtYmVyLFxuICBleGVjdXRpb25Qcm92aWRlcnM6IHJlYWRvbmx5IEluZmVyZW5jZVNlc3Npb24uRXhlY3V0aW9uUHJvdmlkZXJDb25maWdbXSxcbiAgYWxsb2NzOiBudW1iZXJbXSxcbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBmb3IgKGNvbnN0IGVwIG9mIGV4ZWN1dGlvblByb3ZpZGVycykge1xuICAgIGxldCBlcE5hbWUgPSB0eXBlb2YgZXAgPT09ICdzdHJpbmcnID8gZXAgOiBlcC5uYW1lO1xuICAgIGNvbnN0IGVwT3B0aW9uczogQXJyYXk8W251bWJlciwgbnVtYmVyXT4gPSBbXTtcblxuICAgIC8vIGNoZWNrIEVQIG5hbWVcbiAgICBzd2l0Y2ggKGVwTmFtZSkge1xuICAgICAgY2FzZSAnd2Vibm4nOlxuICAgICAgICBlcE5hbWUgPSAnV0VCTk4nO1xuICAgICAgICBpZiAodHlwZW9mIGVwICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIGNvbnN0IHdlYm5uT3B0aW9ucyA9IGVwIGFzIEluZmVyZW5jZVNlc3Npb24uV2ViTk5FeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICAgICAgICAvLyBjb25zdCBjb250ZXh0ID0gKHdlYm5uT3B0aW9ucyBhcyBJbmZlcmVuY2VTZXNzaW9uLldlYk5OT3B0aW9uc1dpdGhNTENvbnRleHQpPy5jb250ZXh0O1xuICAgICAgICAgIGNvbnN0IGRldmljZVR5cGUgPSAod2Vibm5PcHRpb25zIGFzIEluZmVyZW5jZVNlc3Npb24uV2ViTk5Db250ZXh0T3B0aW9ucyk/LmRldmljZVR5cGU7XG4gICAgICAgICAgaWYgKGRldmljZVR5cGUpIHtcbiAgICAgICAgICAgIGFwcGVuZFNlc3Npb25Db25maWcoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsICdkZXZpY2VUeXBlJywgZGV2aWNlVHlwZSwgYWxsb2NzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd3ZWJncHUnOlxuICAgICAgICBpZiAoQlVJTERfREVGUy5VU0VfV0VCR1BVX0VQKSB7XG4gICAgICAgICAgZXBOYW1lID0gJ1dlYkdQVSc7XG4gICAgICAgICAgbGV0IGN1c3RvbURldmljZTogR1BVRGV2aWNlIHwgdW5kZWZpbmVkO1xuXG4gICAgICAgICAgaWYgKHR5cGVvZiBlcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGNvbnN0IGN1c3RvbU9wdGlvbnMgPSBlcCBhcyB1bmtub3duIGFzIHsgZGV2aWNlOiBHUFVEZXZpY2UgfTtcbiAgICAgICAgICAgIGlmIChjdXN0b21PcHRpb25zLmRldmljZSkge1xuICAgICAgICAgICAgICBpZiAodHlwZW9mIEdQVURldmljZSAhPT0gJ3VuZGVmaW5lZCcgJiYgY3VzdG9tT3B0aW9ucy5kZXZpY2UgaW5zdGFuY2VvZiBHUFVEZXZpY2UpIHtcbiAgICAgICAgICAgICAgICBjdXN0b21EZXZpY2UgPSBjdXN0b21PcHRpb25zLmRldmljZTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgR1BVIGRldmljZSBzZXQgaW4gV2ViR1BVIEVQIG9wdGlvbnMuJyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVE9ETzogaGFuZGxlIG1vcmUgb3B0aW9uc1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGluZm8gPSBnZXRJbnN0YW5jZSgpLndlYmdwdVJlZ2lzdGVyRGV2aWNlIShjdXN0b21EZXZpY2UpO1xuICAgICAgICAgIGlmIChpbmZvKSB7XG4gICAgICAgICAgICBjb25zdCBbZGV2aWNlSWQsIGluc3RhbmNlSGFuZGxlLCBkZXZpY2VIYW5kbGVdID0gaW5mbztcbiAgICAgICAgICAgIGFwcGVuZEVwT3B0aW9uKGVwT3B0aW9ucywgJ2RldmljZUlkJywgZGV2aWNlSWQudG9TdHJpbmcoKSwgYWxsb2NzKTtcbiAgICAgICAgICAgIGFwcGVuZEVwT3B0aW9uKGVwT3B0aW9ucywgJ3dlYmdwdUluc3RhbmNlJywgaW5zdGFuY2VIYW5kbGUudG9TdHJpbmcoKSwgYWxsb2NzKTtcbiAgICAgICAgICAgIGFwcGVuZEVwT3B0aW9uKGVwT3B0aW9ucywgJ3dlYmdwdURldmljZScsIGRldmljZUhhbmRsZS50b1N0cmluZygpLCBhbGxvY3MpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlcE5hbWUgPSAnSlMnO1xuICAgICAgICAgIGlmICh0eXBlb2YgZXAgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCB3ZWJncHVPcHRpb25zID0gZXAgYXMgSW5mZXJlbmNlU2Vzc2lvbi5XZWJHcHVFeGVjdXRpb25Qcm92aWRlck9wdGlvbjtcbiAgICAgICAgICAgIGlmICh3ZWJncHVPcHRpb25zPy5wcmVmZXJyZWRMYXlvdXQpIHtcbiAgICAgICAgICAgICAgaWYgKHdlYmdwdU9wdGlvbnMucHJlZmVycmVkTGF5b3V0ICE9PSAnTkNIVycgJiYgd2ViZ3B1T3B0aW9ucy5wcmVmZXJyZWRMYXlvdXQgIT09ICdOSFdDJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgcHJlZmVycmVkTGF5b3V0IG11c3QgYmUgZWl0aGVyICdOQ0hXJyBvciAnTkhXQyc6ICR7d2ViZ3B1T3B0aW9ucy5wcmVmZXJyZWRMYXlvdXR9YCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgYXBwZW5kU2Vzc2lvbkNvbmZpZyhzZXNzaW9uT3B0aW9uc0hhbmRsZSwgJ3ByZWZlcnJlZExheW91dCcsIHdlYmdwdU9wdGlvbnMucHJlZmVycmVkTGF5b3V0LCBhbGxvY3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3dhc20nOlxuICAgICAgY2FzZSAnY3B1JzpcbiAgICAgICAgY29udGludWU7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vdCBzdXBwb3J0ZWQgZXhlY3V0aW9uIHByb3ZpZGVyOiAke2VwTmFtZX1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBlcE5hbWVEYXRhT2Zmc2V0ID0gYWxsb2NXYXNtU3RyaW5nKGVwTmFtZSwgYWxsb2NzKTtcbiAgICBjb25zdCBlcE9wdGlvbnNDb3VudCA9IGVwT3B0aW9ucy5sZW5ndGg7XG4gICAgbGV0IGtleXNPZmZzZXQgPSAwO1xuICAgIGxldCB2YWx1ZXNPZmZzZXQgPSAwO1xuICAgIGlmIChlcE9wdGlvbnNDb3VudCA+IDApIHtcbiAgICAgIGtleXNPZmZzZXQgPSBnZXRJbnN0YW5jZSgpLl9tYWxsb2MoZXBPcHRpb25zQ291bnQgKiBnZXRJbnN0YW5jZSgpLlBUUl9TSVpFKTtcbiAgICAgIGFsbG9jcy5wdXNoKGtleXNPZmZzZXQpO1xuICAgICAgdmFsdWVzT2Zmc2V0ID0gZ2V0SW5zdGFuY2UoKS5fbWFsbG9jKGVwT3B0aW9uc0NvdW50ICogZ2V0SW5zdGFuY2UoKS5QVFJfU0laRSk7XG4gICAgICBhbGxvY3MucHVzaCh2YWx1ZXNPZmZzZXQpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlcE9wdGlvbnNDb3VudDsgaSsrKSB7XG4gICAgICAgIGdldEluc3RhbmNlKCkuc2V0VmFsdWUoa2V5c09mZnNldCArIGkgKiBnZXRJbnN0YW5jZSgpLlBUUl9TSVpFLCBlcE9wdGlvbnNbaV1bMF0sICcqJyk7XG4gICAgICAgIGdldEluc3RhbmNlKCkuc2V0VmFsdWUodmFsdWVzT2Zmc2V0ICsgaSAqIGdldEluc3RhbmNlKCkuUFRSX1NJWkUsIGVwT3B0aW9uc1tpXVsxXSwgJyonKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKFxuICAgICAgKGF3YWl0IGdldEluc3RhbmNlKCkuX09ydEFwcGVuZEV4ZWN1dGlvblByb3ZpZGVyKFxuICAgICAgICBzZXNzaW9uT3B0aW9uc0hhbmRsZSxcbiAgICAgICAgZXBOYW1lRGF0YU9mZnNldCxcbiAgICAgICAga2V5c09mZnNldCxcbiAgICAgICAgdmFsdWVzT2Zmc2V0LFxuICAgICAgICBlcE9wdGlvbnNDb3VudCxcbiAgICAgICkpICE9PSAwXG4gICAgKSB7XG4gICAgICBjaGVja0xhc3RFcnJvcihgQ2FuJ3QgYXBwZW5kIGV4ZWN1dGlvbiBwcm92aWRlcjogJHtlcE5hbWV9LmApO1xuICAgIH1cbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHNldFNlc3Npb25PcHRpb25zID0gYXN5bmMgKG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTogUHJvbWlzZTxbbnVtYmVyLCBudW1iZXJbXV0+ID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gIGxldCBzZXNzaW9uT3B0aW9uc0hhbmRsZSA9IDA7XG4gIGNvbnN0IGFsbG9jczogbnVtYmVyW10gPSBbXTtcblxuICBjb25zdCBzZXNzaW9uT3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIGFwcGVuZERlZmF1bHRPcHRpb25zKHNlc3Npb25PcHRpb25zKTtcblxuICB0cnkge1xuICAgIGNvbnN0IGdyYXBoT3B0aW1pemF0aW9uTGV2ZWwgPSBnZXRHcmFwaE9wdGltemF0aW9uTGV2ZWwoc2Vzc2lvbk9wdGlvbnMuZ3JhcGhPcHRpbWl6YXRpb25MZXZlbCA/PyAnYWxsJyk7XG4gICAgY29uc3QgZXhlY3V0aW9uTW9kZSA9IGdldEV4ZWN1dGlvbk1vZGUoc2Vzc2lvbk9wdGlvbnMuZXhlY3V0aW9uTW9kZSA/PyAnc2VxdWVudGlhbCcpO1xuICAgIGNvbnN0IGxvZ0lkRGF0YU9mZnNldCA9XG4gICAgICB0eXBlb2Ygc2Vzc2lvbk9wdGlvbnMubG9nSWQgPT09ICdzdHJpbmcnID8gYWxsb2NXYXNtU3RyaW5nKHNlc3Npb25PcHRpb25zLmxvZ0lkLCBhbGxvY3MpIDogMDtcblxuICAgIGNvbnN0IGxvZ1NldmVyaXR5TGV2ZWwgPSBzZXNzaW9uT3B0aW9ucy5sb2dTZXZlcml0eUxldmVsID8/IDI7IC8vIERlZmF1bHQgdG8gMiAtIHdhcm5pbmdcbiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIobG9nU2V2ZXJpdHlMZXZlbCkgfHwgbG9nU2V2ZXJpdHlMZXZlbCA8IDAgfHwgbG9nU2V2ZXJpdHlMZXZlbCA+IDQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgbG9nIHNlcnZlcml0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7bG9nU2V2ZXJpdHlMZXZlbH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBsb2dWZXJib3NpdHlMZXZlbCA9IHNlc3Npb25PcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsID8/IDA7IC8vIERlZmF1bHQgdG8gMCAtIHZlcmJvc2VcbiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIobG9nVmVyYm9zaXR5TGV2ZWwpIHx8IGxvZ1ZlcmJvc2l0eUxldmVsIDwgMCB8fCBsb2dWZXJib3NpdHlMZXZlbCA+IDQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgbG9nIHZlcmJvc2l0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7bG9nVmVyYm9zaXR5TGV2ZWx9YCk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3B0aW1pemVkTW9kZWxGaWxlUGF0aE9mZnNldCA9XG4gICAgICB0eXBlb2Ygc2Vzc2lvbk9wdGlvbnMub3B0aW1pemVkTW9kZWxGaWxlUGF0aCA9PT0gJ3N0cmluZydcbiAgICAgICAgPyBhbGxvY1dhc21TdHJpbmcoc2Vzc2lvbk9wdGlvbnMub3B0aW1pemVkTW9kZWxGaWxlUGF0aCwgYWxsb2NzKVxuICAgICAgICA6IDA7XG5cbiAgICBzZXNzaW9uT3B0aW9uc0hhbmRsZSA9IHdhc20uX09ydENyZWF0ZVNlc3Npb25PcHRpb25zKFxuICAgICAgZ3JhcGhPcHRpbWl6YXRpb25MZXZlbCxcbiAgICAgICEhc2Vzc2lvbk9wdGlvbnMuZW5hYmxlQ3B1TWVtQXJlbmEsXG4gICAgICAhIXNlc3Npb25PcHRpb25zLmVuYWJsZU1lbVBhdHRlcm4sXG4gICAgICBleGVjdXRpb25Nb2RlLFxuICAgICAgISFzZXNzaW9uT3B0aW9ucy5lbmFibGVQcm9maWxpbmcsXG4gICAgICAwLFxuICAgICAgbG9nSWREYXRhT2Zmc2V0LFxuICAgICAgbG9nU2V2ZXJpdHlMZXZlbCxcbiAgICAgIGxvZ1ZlcmJvc2l0eUxldmVsLFxuICAgICAgb3B0aW1pemVkTW9kZWxGaWxlUGF0aE9mZnNldCxcbiAgICApO1xuICAgIGlmIChzZXNzaW9uT3B0aW9uc0hhbmRsZSA9PT0gMCkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBjcmVhdGUgc2Vzc2lvbiBvcHRpb25zLlwiKTtcbiAgICB9XG5cbiAgICBpZiAoc2Vzc2lvbk9wdGlvbnMuZXhlY3V0aW9uUHJvdmlkZXJzKSB7XG4gICAgICBhd2FpdCBzZXRFeGVjdXRpb25Qcm92aWRlcnMoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIHNlc3Npb25PcHRpb25zLmV4ZWN1dGlvblByb3ZpZGVycywgYWxsb2NzKTtcbiAgICB9XG5cbiAgICBpZiAoc2Vzc2lvbk9wdGlvbnMuZW5hYmxlR3JhcGhDYXB0dXJlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmICh0eXBlb2Ygc2Vzc2lvbk9wdGlvbnMuZW5hYmxlR3JhcGhDYXB0dXJlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBlbmFibGVHcmFwaENhcHR1cmUgbXVzdCBiZSBhIGJvb2xlYW4gdmFsdWU6ICR7c2Vzc2lvbk9wdGlvbnMuZW5hYmxlR3JhcGhDYXB0dXJlfWApO1xuICAgICAgfVxuICAgICAgYXBwZW5kU2Vzc2lvbkNvbmZpZyhcbiAgICAgICAgc2Vzc2lvbk9wdGlvbnNIYW5kbGUsXG4gICAgICAgICdlbmFibGVHcmFwaENhcHR1cmUnLFxuICAgICAgICBzZXNzaW9uT3B0aW9ucy5lbmFibGVHcmFwaENhcHR1cmUudG9TdHJpbmcoKSxcbiAgICAgICAgYWxsb2NzLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoc2Vzc2lvbk9wdGlvbnMuZnJlZURpbWVuc2lvbk92ZXJyaWRlcykge1xuICAgICAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHNlc3Npb25PcHRpb25zLmZyZWVEaW1lbnNpb25PdmVycmlkZXMpKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGZyZWUgZGltZW5zaW9uIG92ZXJyaWRlIG5hbWUgbXVzdCBiZSBhIHN0cmluZzogJHtuYW1lfWApO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSB8fCB2YWx1ZSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGZyZWUgZGltZW5zaW9uIG92ZXJyaWRlIHZhbHVlIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlcjogJHt2YWx1ZX1gKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBuYW1lT2Zmc2V0ID0gYWxsb2NXYXNtU3RyaW5nKG5hbWUsIGFsbG9jcyk7XG4gICAgICAgIGlmICh3YXNtLl9PcnRBZGRGcmVlRGltZW5zaW9uT3ZlcnJpZGUoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIG5hbWVPZmZzZXQsIHZhbHVlKSAhPT0gMCkge1xuICAgICAgICAgIGNoZWNrTGFzdEVycm9yKGBDYW4ndCBzZXQgYSBmcmVlIGRpbWVuc2lvbiBvdmVycmlkZTogJHtuYW1lfSAtICR7dmFsdWV9LmApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHNlc3Npb25PcHRpb25zLmV4dHJhICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGl0ZXJhdGVFeHRyYU9wdGlvbnMoc2Vzc2lvbk9wdGlvbnMuZXh0cmEsICcnLCBuZXcgV2Vha1NldDxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oKSwgKGtleSwgdmFsdWUpID0+IHtcbiAgICAgICAgYXBwZW5kU2Vzc2lvbkNvbmZpZyhzZXNzaW9uT3B0aW9uc0hhbmRsZSwga2V5LCB2YWx1ZSwgYWxsb2NzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBbc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIGFsbG9jc107XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoc2Vzc2lvbk9wdGlvbnNIYW5kbGUgIT09IDApIHtcbiAgICAgIGlmICh3YXNtLl9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnMoc2Vzc2lvbk9wdGlvbnNIYW5kbGUpICE9PSAwKSB7XG4gICAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgcmVsZWFzZSBzZXNzaW9uIG9wdGlvbnMuXCIpO1xuICAgICAgfVxuICAgIH1cbiAgICBhbGxvY3MuZm9yRWFjaCgoYWxsb2MpID0+IHdhc20uX2ZyZWUoYWxsb2MpKTtcbiAgICB0aHJvdyBlO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUZW5zb3IgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG4vLyBhIGR1bW15IHR5cGUgZGVjbGFyYXRpb24gZm9yIEZsb2F0MTZBcnJheSBpbiBjYXNlIGFueSBwb2x5ZmlsbCBpcyBhdmFpbGFibGUuXG5kZWNsYXJlIGdsb2JhbCB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb24sIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgY29uc3QgRmxvYXQxNkFycmF5OiBhbnk7XG59XG5cbi8vIFRoaXMgZmlsZSBpbmNsdWRlcyBjb21tb24gZGVmaW5pdGlvbnMuIFRoZXkgZG8gTk9UIGhhdmUgZGVwZW5kZW5jeSBvbiB0aGUgV2ViQXNzZW1ibHkgaW5zdGFuY2UuXG5cbi8qKlxuICogQ29waWVkIGZyb20gT05OWCBkZWZpbml0aW9uLiBVc2UgdGhpcyB0byBkcm9wIGRlcGVuZGVuY3kgJ29ubnhfcHJvdG8nIHRvIGRlY3JlYXNlIGNvbXBpbGVkIC5qcyBmaWxlIHNpemUuXG4gKi9cbmV4cG9ydCBjb25zdCBlbnVtIERhdGFUeXBlIHtcbiAgdW5kZWZpbmVkID0gMCxcbiAgZmxvYXQgPSAxLFxuICB1aW50OCA9IDIsXG4gIGludDggPSAzLFxuICB1aW50MTYgPSA0LFxuICBpbnQxNiA9IDUsXG4gIGludDMyID0gNixcbiAgaW50NjQgPSA3LFxuICBzdHJpbmcgPSA4LFxuICBib29sID0gOSxcbiAgZmxvYXQxNiA9IDEwLFxuICBkb3VibGUgPSAxMSxcbiAgdWludDMyID0gMTIsXG4gIHVpbnQ2NCA9IDEzLFxuICBjb21wbGV4NjQgPSAxNCxcbiAgY29tcGxleDEyOCA9IDE1LFxuICBiZmxvYXQxNiA9IDE2LFxuXG4gIC8vIDQtYml0IGRhdGEtdHlwZXNcbiAgdWludDQgPSAyMSxcbiAgaW50NCA9IDIyLFxufVxuXG4vKipcbiAqIE1hcCBzdHJpbmcgdGVuc29yIGRhdGEgdG8gZW51bSB2YWx1ZVxuICovXG5leHBvcnQgY29uc3QgdGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0gPSAodHlwZTogc3RyaW5nKTogRGF0YVR5cGUgPT4ge1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlICdpbnQ4JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5pbnQ4O1xuICAgIGNhc2UgJ3VpbnQ4JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS51aW50ODtcbiAgICBjYXNlICdib29sJzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5ib29sO1xuICAgIGNhc2UgJ2ludDE2JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5pbnQxNjtcbiAgICBjYXNlICd1aW50MTYnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLnVpbnQxNjtcbiAgICBjYXNlICdpbnQzMic6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuaW50MzI7XG4gICAgY2FzZSAndWludDMyJzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS51aW50MzI7XG4gICAgY2FzZSAnZmxvYXQxNic6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuZmxvYXQxNjtcbiAgICBjYXNlICdmbG9hdDMyJzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5mbG9hdDtcbiAgICBjYXNlICdmbG9hdDY0JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5kb3VibGU7XG4gICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5zdHJpbmc7XG4gICAgY2FzZSAnaW50NjQnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmludDY0O1xuICAgIGNhc2UgJ3VpbnQ2NCc6XG4gICAgICByZXR1cm4gRGF0YVR5cGUudWludDY0O1xuICAgIGNhc2UgJ2ludDQnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmludDQ7XG4gICAgY2FzZSAndWludDQnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLnVpbnQ0O1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke3R5cGV9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogTWFwIGVudW0gdmFsdWUgdG8gc3RyaW5nIHRlbnNvciBkYXRhXG4gKi9cbmV4cG9ydCBjb25zdCB0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyA9ICh0eXBlUHJvdG86IERhdGFUeXBlKTogVGVuc29yLlR5cGUgPT4ge1xuICBzd2l0Y2ggKHR5cGVQcm90bykge1xuICAgIGNhc2UgRGF0YVR5cGUuaW50ODpcbiAgICAgIHJldHVybiAnaW50OCc7XG4gICAgY2FzZSBEYXRhVHlwZS51aW50ODpcbiAgICAgIHJldHVybiAndWludDgnO1xuICAgIGNhc2UgRGF0YVR5cGUuYm9vbDpcbiAgICAgIHJldHVybiAnYm9vbCc7XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQxNjpcbiAgICAgIHJldHVybiAnaW50MTYnO1xuICAgIGNhc2UgRGF0YVR5cGUudWludDE2OlxuICAgICAgcmV0dXJuICd1aW50MTYnO1xuICAgIGNhc2UgRGF0YVR5cGUuaW50MzI6XG4gICAgICByZXR1cm4gJ2ludDMyJztcbiAgICBjYXNlIERhdGFUeXBlLnVpbnQzMjpcbiAgICAgIHJldHVybiAndWludDMyJztcbiAgICBjYXNlIERhdGFUeXBlLmZsb2F0MTY6XG4gICAgICByZXR1cm4gJ2Zsb2F0MTYnO1xuICAgIGNhc2UgRGF0YVR5cGUuZmxvYXQ6XG4gICAgICByZXR1cm4gJ2Zsb2F0MzInO1xuICAgIGNhc2UgRGF0YVR5cGUuZG91YmxlOlxuICAgICAgcmV0dXJuICdmbG9hdDY0JztcbiAgICBjYXNlIERhdGFUeXBlLnN0cmluZzpcbiAgICAgIHJldHVybiAnc3RyaW5nJztcbiAgICBjYXNlIERhdGFUeXBlLmludDY0OlxuICAgICAgcmV0dXJuICdpbnQ2NCc7XG4gICAgY2FzZSBEYXRhVHlwZS51aW50NjQ6XG4gICAgICByZXR1cm4gJ3VpbnQ2NCc7XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQ0OlxuICAgICAgcmV0dXJuICdpbnQ0JztcbiAgICBjYXNlIERhdGFUeXBlLnVpbnQ0OlxuICAgICAgcmV0dXJuICd1aW50NCc7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7dHlwZVByb3RvfWApO1xuICB9XG59O1xuXG4vKipcbiAqIGdldCB0ZW5zb3Igc2l6ZSBpbiBieXRlcyBieSB0aGUgZ2l2ZW4gZGF0YSB0eXBlIGFuZCBkaW1lbnNpb25zXG4gKiBAcmV0dXJucyBzaXplIGluIGludGVnZXIgb3IgdW5kZWZpbmVkIGlmIHRoZSBkYXRhIHR5cGUgaXMgbm90IHN1cHBvcnRlZFxuICovXG5leHBvcnQgY29uc3QgY2FsY3VsYXRlVGVuc29yU2l6ZUluQnl0ZXMgPSAoXG4gIGRhdGVUeXBlOiBudW1iZXIsXG4gIGRpbXNPclNpemU6IHJlYWRvbmx5IG51bWJlcltdIHwgbnVtYmVyLFxuKTogbnVtYmVyIHwgdW5kZWZpbmVkID0+IHtcbiAgY29uc3QgZWxlbWVudFNpemUgPSBbXG4gICAgLTEsIC8vIHVuZGVmaW5lZCA9IDBcbiAgICA0LCAvLyBmbG9hdCA9IDFcbiAgICAxLCAvLyB1aW50OCA9IDJcbiAgICAxLCAvLyBpbnQ4ID0gM1xuICAgIDIsIC8vIHVpbnQxNiA9IDRcbiAgICAyLCAvLyBpbnQxNiA9IDVcbiAgICA0LCAvLyBpbnQzMiA9IDZcbiAgICA4LCAvLyBpbnQ2NCA9IDdcbiAgICAtMSwgLy8gc3RyaW5nID0gOFxuICAgIDEsIC8vIGJvb2wgPSA5XG4gICAgMiwgLy8gZmxvYXQxNiA9IDEwXG4gICAgOCwgLy8gZG91YmxlID0gMTFcbiAgICA0LCAvLyB1aW50MzIgPSAxMlxuICAgIDgsIC8vIHVpbnQ2NCA9IDEzXG4gICAgLTEsIC8vIGNvbXBsZXg2NCA9IDE0XG4gICAgLTEsIC8vIGNvbXBsZXgxMjggPSAxNVxuICAgIC0xLCAvLyBiZmxvYXQxNiA9IDE2XG4gICAgLTEsIC8vIEZMT0FUOEU0TTNGTiA9IDE3XG4gICAgLTEsIC8vIEZMT0FUOEU0TTNGTlVaID0gMThcbiAgICAtMSwgLy8gRkxPQVQ4RTVNMiA9IDE5XG4gICAgLTEsIC8vIEZMT0FUOEU1TTJGTlVaID0gMjBcbiAgICAwLjUsIC8vIHVpbnQ0ID0gMjFcbiAgICAwLjUsIC8vIGludDQgPSAyMlxuICBdW2RhdGVUeXBlXTtcblxuICBjb25zdCBzaXplID0gdHlwZW9mIGRpbXNPclNpemUgPT09ICdudW1iZXInID8gZGltc09yU2l6ZSA6IGRpbXNPclNpemUucmVkdWNlKChhLCBiKSA9PiBhICogYiwgMSk7XG4gIHJldHVybiBlbGVtZW50U2l6ZSA+IDAgPyBNYXRoLmNlaWwoc2l6ZSAqIGVsZW1lbnRTaXplKSA6IHVuZGVmaW5lZDtcbn07XG5cbi8qKlxuICogZ2V0IHR5cGVkIGFycmF5IGNvbnN0cnVjdG9yIGJ5IHRoZSBnaXZlbiB0ZW5zb3IgdHlwZVxuICovXG5leHBvcnQgY29uc3QgdGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yID0gKFxuICB0eXBlOiBUZW5zb3IuVHlwZSxcbik6XG4gIHwgRmxvYXQzMkFycmF5Q29uc3RydWN0b3JcbiAgfCBVaW50OEFycmF5Q29uc3RydWN0b3JcbiAgfCBJbnQ4QXJyYXlDb25zdHJ1Y3RvclxuICB8IFVpbnQxNkFycmF5Q29uc3RydWN0b3JcbiAgfCBJbnQxNkFycmF5Q29uc3RydWN0b3JcbiAgfCBJbnQzMkFycmF5Q29uc3RydWN0b3JcbiAgfCBCaWdJbnQ2NEFycmF5Q29uc3RydWN0b3JcbiAgfCBVaW50OEFycmF5Q29uc3RydWN0b3JcbiAgfCBGbG9hdDY0QXJyYXlDb25zdHJ1Y3RvclxuICB8IFVpbnQzMkFycmF5Q29uc3RydWN0b3JcbiAgfCBCaWdVaW50NjRBcnJheUNvbnN0cnVjdG9yID0+IHtcbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSAnZmxvYXQxNic6XG4gICAgICAvLyBhbGxvdyBGbG9hdDE2QXJyYXkgcG9seWZpbGwuXG4gICAgICByZXR1cm4gdHlwZW9mIEZsb2F0MTZBcnJheSAhPT0gJ3VuZGVmaW5lZCcgJiYgRmxvYXQxNkFycmF5LmZyb20gPyBGbG9hdDE2QXJyYXkgOiBVaW50MTZBcnJheTtcbiAgICBjYXNlICdmbG9hdDMyJzpcbiAgICAgIHJldHVybiBGbG9hdDMyQXJyYXk7XG4gICAgY2FzZSAndWludDgnOlxuICAgICAgcmV0dXJuIFVpbnQ4QXJyYXk7XG4gICAgY2FzZSAnaW50OCc6XG4gICAgICByZXR1cm4gSW50OEFycmF5O1xuICAgIGNhc2UgJ3VpbnQxNic6XG4gICAgICByZXR1cm4gVWludDE2QXJyYXk7XG4gICAgY2FzZSAnaW50MTYnOlxuICAgICAgcmV0dXJuIEludDE2QXJyYXk7XG4gICAgY2FzZSAnaW50MzInOlxuICAgICAgcmV0dXJuIEludDMyQXJyYXk7XG4gICAgY2FzZSAnYm9vbCc6XG4gICAgICByZXR1cm4gVWludDhBcnJheTtcbiAgICBjYXNlICdmbG9hdDY0JzpcbiAgICAgIHJldHVybiBGbG9hdDY0QXJyYXk7XG4gICAgY2FzZSAndWludDMyJzpcbiAgICAgIHJldHVybiBVaW50MzJBcnJheTtcbiAgICBjYXNlICdpbnQ2NCc6XG4gICAgICByZXR1cm4gQmlnSW50NjRBcnJheTtcbiAgICBjYXNlICd1aW50NjQnOlxuICAgICAgcmV0dXJuIEJpZ1VpbnQ2NEFycmF5O1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGU6ICR7dHlwZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBNYXAgc3RyaW5nIGxvZyBsZXZlbCB0byBpbnRlZ2VyIHZhbHVlXG4gKi9cbmV4cG9ydCBjb25zdCBsb2dMZXZlbFN0cmluZ1RvRW51bSA9IChsb2dMZXZlbD86ICd2ZXJib3NlJyB8ICdpbmZvJyB8ICd3YXJuaW5nJyB8ICdlcnJvcicgfCAnZmF0YWwnKTogbnVtYmVyID0+IHtcbiAgc3dpdGNoIChsb2dMZXZlbCkge1xuICAgIGNhc2UgJ3ZlcmJvc2UnOlxuICAgICAgcmV0dXJuIDA7XG4gICAgY2FzZSAnaW5mbyc6XG4gICAgICByZXR1cm4gMTtcbiAgICBjYXNlICd3YXJuaW5nJzpcbiAgICAgIHJldHVybiAyO1xuICAgIGNhc2UgJ2Vycm9yJzpcbiAgICAgIHJldHVybiAzO1xuICAgIGNhc2UgJ2ZhdGFsJzpcbiAgICAgIHJldHVybiA0O1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGxvZ2dpbmcgbGV2ZWw6ICR7bG9nTGV2ZWx9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogQ2hlY2sgd2hldGhlciB0aGUgZ2l2ZW4gdGVuc29yIHR5cGUgaXMgc3VwcG9ydGVkIGJ5IEdQVSBidWZmZXJcbiAqL1xuZXhwb3J0IGNvbnN0IGlzR3B1QnVmZmVyU3VwcG9ydGVkVHlwZSA9ICh0eXBlOiBUZW5zb3IuVHlwZSk6IHR5cGUgaXMgVGVuc29yLkdwdUJ1ZmZlckRhdGFUeXBlcyA9PlxuICB0eXBlID09PSAnZmxvYXQzMicgfHxcbiAgdHlwZSA9PT0gJ2Zsb2F0MTYnIHx8XG4gIHR5cGUgPT09ICdpbnQzMicgfHxcbiAgdHlwZSA9PT0gJ2ludDY0JyB8fFxuICB0eXBlID09PSAndWludDMyJyB8fFxuICB0eXBlID09PSAndWludDgnIHx8XG4gIHR5cGUgPT09ICdib29sJyB8fFxuICB0eXBlID09PSAndWludDQnIHx8XG4gIHR5cGUgPT09ICdpbnQ0JztcblxuLyoqXG4gKiBDaGVjayB3aGV0aGVyIHRoZSBnaXZlbiB0ZW5zb3IgdHlwZSBpcyBzdXBwb3J0ZWQgYnkgV2ViTk4gTUxUZW5zb3JcbiAqL1xuZXhwb3J0IGNvbnN0IGlzTUxUZW5zb3JTdXBwb3J0ZWRUeXBlID0gKHR5cGU6IFRlbnNvci5UeXBlKTogdHlwZSBpcyBUZW5zb3IuTUxUZW5zb3JEYXRhVHlwZXMgPT5cbiAgdHlwZSA9PT0gJ2Zsb2F0MzInIHx8XG4gIHR5cGUgPT09ICdmbG9hdDE2JyB8fFxuICB0eXBlID09PSAnaW50MzInIHx8XG4gIHR5cGUgPT09ICdpbnQ2NCcgfHxcbiAgdHlwZSA9PT0gJ3VpbnQzMicgfHxcbiAgdHlwZSA9PT0gJ3VpbnQ2NCcgfHxcbiAgdHlwZSA9PT0gJ2ludDgnIHx8XG4gIHR5cGUgPT09ICd1aW50OCcgfHxcbiAgdHlwZSA9PT0gJ2Jvb2wnIHx8XG4gIHR5cGUgPT09ICd1aW50NCcgfHxcbiAgdHlwZSA9PT0gJ2ludDQnO1xuXG4vKipcbiAqIE1hcCBzdHJpbmcgZGF0YSBsb2NhdGlvbiB0byBpbnRlZ2VyIHZhbHVlXG4gKi9cbmV4cG9ydCBjb25zdCBkYXRhTG9jYXRpb25TdHJpbmdUb0VudW0gPSAobG9jYXRpb246IFRlbnNvci5EYXRhTG9jYXRpb24pOiBudW1iZXIgPT4ge1xuICBzd2l0Y2ggKGxvY2F0aW9uKSB7XG4gICAgY2FzZSAnbm9uZSc6XG4gICAgICByZXR1cm4gMDtcbiAgICBjYXNlICdjcHUnOlxuICAgICAgcmV0dXJuIDE7XG4gICAgY2FzZSAnY3B1LXBpbm5lZCc6XG4gICAgICByZXR1cm4gMjtcbiAgICBjYXNlICd0ZXh0dXJlJzpcbiAgICAgIHJldHVybiAzO1xuICAgIGNhc2UgJ2dwdS1idWZmZXInOlxuICAgICAgcmV0dXJuIDQ7XG4gICAgY2FzZSAnbWwtdGVuc29yJzpcbiAgICAgIHJldHVybiA1O1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGRhdGEgbG9jYXRpb246ICR7bG9jYXRpb259YCk7XG4gIH1cbn07XG5cbi8qKlxuICogTWFwIGludGVnZXIgZGF0YSBsb2NhdGlvbiB0byBzdHJpbmcgdmFsdWVcbiAqL1xuZXhwb3J0IGNvbnN0IGRhdGFMb2NhdGlvbkVudW1Ub1N0cmluZyA9IChsb2NhdGlvbjogbnVtYmVyKTogVGVuc29yLkRhdGFMb2NhdGlvbiB8IHVuZGVmaW5lZCA9PlxuICAoWydub25lJywgJ2NwdScsICdjcHUtcGlubmVkJywgJ3RleHR1cmUnLCAnZ3B1LWJ1ZmZlcicsICdtbC10ZW5zb3InXSBhcyBjb25zdClbbG9jYXRpb25dO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBpc05vZGUgfSBmcm9tICcuL3dhc20tdXRpbHMtZW52JztcblxuLyoqXG4gKiBMb2FkIGEgZmlsZSBpbnRvIGEgVWludDhBcnJheS5cbiAqXG4gKiBAcGFyYW0gZmlsZSAtIHRoZSBmaWxlIHRvIGxvYWQuIENhbiBiZSBhIFVSTC9wYXRoLCBhIEJsb2IsIGFuIEFycmF5QnVmZmVyLCBvciBhIFVpbnQ4QXJyYXkuXG4gKiBAcmV0dXJucyBhIFVpbnQ4QXJyYXkgY29udGFpbmluZyB0aGUgZmlsZSBkYXRhLlxuICovXG5leHBvcnQgY29uc3QgbG9hZEZpbGUgPSBhc3luYyAoZmlsZTogc3RyaW5nIHwgQmxvYiB8IEFycmF5QnVmZmVyTGlrZSB8IFVpbnQ4QXJyYXkpOiBQcm9taXNlPFVpbnQ4QXJyYXk+ID0+IHtcbiAgaWYgKHR5cGVvZiBmaWxlID09PSAnc3RyaW5nJykge1xuICAgIGlmIChpc05vZGUpIHtcbiAgICAgIC8vIGxvYWQgZmlsZSBpbnRvIEFycmF5QnVmZmVyIGluIE5vZGUuanNcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHsgcmVhZEZpbGUgfSA9IHJlcXVpcmUoJ25vZGU6ZnMvcHJvbWlzZXMnKTtcbiAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGF3YWl0IHJlYWRGaWxlKGZpbGUpKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGUuY29kZSA9PT0gJ0VSUl9GU19GSUxFX1RPT19MQVJHRScpIHtcbiAgICAgICAgICAvLyBmaWxlIGlzIHRvbyBsYXJnZSwgdXNlIGZzLmNyZWF0ZVJlYWRTdHJlYW0gaW5zdGVhZFxuICAgICAgICAgIGNvbnN0IHsgY3JlYXRlUmVhZFN0cmVhbSB9ID0gcmVxdWlyZSgnbm9kZTpmcycpO1xuICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNyZWF0ZVJlYWRTdHJlYW0oZmlsZSk7XG4gICAgICAgICAgY29uc3QgY2h1bmtzOiBVaW50OEFycmF5W10gPSBbXTtcbiAgICAgICAgICBmb3IgYXdhaXQgKGNvbnN0IGNodW5rIG9mIHN0cmVhbSkge1xuICAgICAgICAgICAgY2h1bmtzLnB1c2goY2h1bmspO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoQnVmZmVyLmNvbmNhdChjaHVua3MpKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBsb2FkIGZpbGUgaW50byBBcnJheUJ1ZmZlciBpbiBicm93c2Vyc1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChmaWxlKTtcbiAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBmYWlsZWQgdG8gbG9hZCBleHRlcm5hbCBkYXRhIGZpbGU6ICR7ZmlsZX1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNvbnRlbnRMZW5ndGhIZWFkZXIgPSByZXNwb25zZS5oZWFkZXJzLmdldCgnQ29udGVudC1MZW5ndGgnKTtcbiAgICAgIGNvbnN0IGZpbGVTaXplID0gY29udGVudExlbmd0aEhlYWRlciA/IHBhcnNlSW50KGNvbnRlbnRMZW5ndGhIZWFkZXIsIDEwKSA6IDA7XG4gICAgICBpZiAoZmlsZVNpemUgPCAxMDczNzQxODI0IC8qIDFHQiAqLykge1xuICAgICAgICAvLyB3aGVuIENvbnRlbnQtTGVuZ3RoIGhlYWRlciBpcyBub3Qgc2V0LCB3ZSBjYW5ub3QgZGV0ZXJtaW5lIHRoZSBmaWxlIHNpemUuIFdlIGFzc3VtZSBpdCBpcyBzbWFsbCBlbm91Z2ggdG9cbiAgICAgICAgLy8gbG9hZCBpbnRvIG1lbW9yeS5cbiAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGF3YWl0IHJlc3BvbnNlLmFycmF5QnVmZmVyKCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gZmlsZSBpcyB0b28gbGFyZ2UsIHVzZSBzdHJlYW0gaW5zdGVhZFxuICAgICAgICBpZiAoIXJlc3BvbnNlLmJvZHkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGZhaWxlZCB0byBsb2FkIGV4dGVybmFsIGRhdGEgZmlsZTogJHtmaWxlfSwgbm8gcmVzcG9uc2UgYm9keS5gKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZWFkZXIgPSByZXNwb25zZS5ib2R5LmdldFJlYWRlcigpO1xuXG4gICAgICAgIGxldCBidWZmZXI7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gdHJ5IHRvIGNyZWF0ZSBBcnJheUJ1ZmZlciBkaXJlY3RseVxuICAgICAgICAgIGJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcihmaWxlU2l6ZSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFJhbmdlRXJyb3IpIHtcbiAgICAgICAgICAgIC8vIHVzZSBXZWJBc3NlbWJseSBNZW1vcnkgdG8gYWxsb2NhdGUgbGFyZ2VyIEFycmF5QnVmZmVyXG4gICAgICAgICAgICBjb25zdCBwYWdlcyA9IE1hdGguY2VpbChmaWxlU2l6ZSAvIDY1NTM2KTtcbiAgICAgICAgICAgIGJ1ZmZlciA9IG5ldyBXZWJBc3NlbWJseS5NZW1vcnkoeyBpbml0aWFsOiBwYWdlcywgbWF4aW11bTogcGFnZXMgfSkuYnVmZmVyO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBvZmZzZXQgPSAwO1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc3RhbnQtY29uZGl0aW9uXG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgY29uc3QgeyBkb25lLCB2YWx1ZSB9ID0gYXdhaXQgcmVhZGVyLnJlYWQoKTtcbiAgICAgICAgICBpZiAoZG9uZSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IGNodW5rU2l6ZSA9IHZhbHVlLmJ5dGVMZW5ndGg7XG4gICAgICAgICAgY29uc3QgY2h1bmsgPSBuZXcgVWludDhBcnJheShidWZmZXIsIG9mZnNldCwgY2h1bmtTaXplKTtcbiAgICAgICAgICBjaHVuay5zZXQodmFsdWUpO1xuICAgICAgICAgIG9mZnNldCArPSBjaHVua1NpemU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGJ1ZmZlciwgMCwgZmlsZVNpemUpO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmIChmaWxlIGluc3RhbmNlb2YgQmxvYikge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShhd2FpdCBmaWxlLmFycmF5QnVmZmVyKCkpO1xuICB9IGVsc2UgaWYgKGZpbGUgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgcmV0dXJuIGZpbGU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGZpbGUpO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBFbnYgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBsb2dMZXZlbFN0cmluZ1RvRW51bSB9IGZyb20gJy4uL3dhc20tY29tbW9uJztcblxudHlwZSBMb2dMZXZlbCA9IE5vbk51bGxhYmxlPEVudlsnbG9nTGV2ZWwnXT47XG50eXBlIE1lc3NhZ2VTdHJpbmcgPSBzdHJpbmc7XG50eXBlIE1lc3NhZ2VGdW5jdGlvbiA9ICgpID0+IHN0cmluZztcbnR5cGUgTWVzc2FnZSA9IE1lc3NhZ2VTdHJpbmcgfCBNZXNzYWdlRnVuY3Rpb247XG5cbmNvbnN0IGxvZ0xldmVsUHJlZml4ID0gWydWJywgJ0knLCAnVycsICdFJywgJ0YnXTtcblxuY29uc3QgZG9Mb2cgPSAobGV2ZWw6IG51bWJlciwgbWVzc2FnZTogc3RyaW5nKTogdm9pZCA9PiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUubG9nKGBbJHtsb2dMZXZlbFByZWZpeFtsZXZlbF19LCR7bmV3IERhdGUoKS50b0lTT1N0cmluZygpfV0ke21lc3NhZ2V9YCk7XG59O1xuXG5sZXQgY29uZmlnTG9nTGV2ZWw6IExvZ0xldmVsIHwgdW5kZWZpbmVkO1xubGV0IGRlYnVnOiBib29sZWFuIHwgdW5kZWZpbmVkO1xuXG5leHBvcnQgY29uc3QgY29uZmlndXJlTG9nZ2VyID0gKCRjb25maWdMb2dMZXZlbDogTG9nTGV2ZWwsICRkZWJ1ZzogYm9vbGVhbik6IHZvaWQgPT4ge1xuICBjb25maWdMb2dMZXZlbCA9ICRjb25maWdMb2dMZXZlbDtcbiAgZGVidWcgPSAkZGVidWc7XG59O1xuXG4vKipcbiAqIEEgc2ltcGxlIGxvZ2dpbmcgdXRpbGl0eSB0byBsb2cgbWVzc2FnZXMgdG8gdGhlIGNvbnNvbGUuXG4gKi9cbmV4cG9ydCBjb25zdCBMT0cgPSAobG9nTGV2ZWw6IExvZ0xldmVsLCBtc2c6IE1lc3NhZ2UpOiB2b2lkID0+IHtcbiAgY29uc3QgbWVzc2FnZUxldmVsID0gbG9nTGV2ZWxTdHJpbmdUb0VudW0obG9nTGV2ZWwpO1xuICBjb25zdCBjb25maWdMZXZlbCA9IGxvZ0xldmVsU3RyaW5nVG9FbnVtKGNvbmZpZ0xvZ0xldmVsKTtcbiAgaWYgKG1lc3NhZ2VMZXZlbCA+PSBjb25maWdMZXZlbCkge1xuICAgIGRvTG9nKG1lc3NhZ2VMZXZlbCwgdHlwZW9mIG1zZyA9PT0gJ2Z1bmN0aW9uJyA/IG1zZygpIDogbXNnKTtcbiAgfVxufTtcblxuLyoqXG4gKiBBIHNpbXBsZSBsb2dnaW5nIHV0aWxpdHkgdG8gbG9nIG1lc3NhZ2VzIHRvIHRoZSBjb25zb2xlLiBPbmx5IGxvZ3Mgd2hlbiBkZWJ1ZyBpcyBlbmFibGVkLlxuICovXG5leHBvcnQgY29uc3QgTE9HX0RFQlVHOiB0eXBlb2YgTE9HID0gKC4uLmFyZ3M6IFBhcmFtZXRlcnM8dHlwZW9mIExPRz4pID0+IHtcbiAgaWYgKGRlYnVnKSB7XG4gICAgTE9HKC4uLmFyZ3MpO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1wYXJhbS1yZWFzc2lnbiAqL1xuXG5leHBvcnQgY2xhc3MgTWF0TXVsVXRpbCB7XG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIGV4cGVjdGVkIHNoYXBlIHdoZW4gbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAqIEBwYXJhbSBhIFRoZSBzaGFwZSBvZiB0ZW5zb3IgQS4gU2hvdWxkIGJlIGEgdHVwbGUgb2YgMiBwb3NpdGl2ZSBpbnRlZ2Vyc1xuICAgKiBAcGFyYW0gYiBUaGUgc2hhcGUgb2YgdGVuc29yIEIuIFNob3VsZCBiZSBhIHR1cGxlIG9mIDIgcG9zaXRpdmUgaW50ZWdlcnNcbiAgICogQHJldHVybnMgVGhlIGV4cGVjdGVkIHNoYXBlIG9mIHRoZSByZXN1bHQsIG9yIHVuZGVmaW5lZCBpZiBOL0FcbiAgICovXG4gIHN0YXRpYyBjYWxjTWF0TXVsU2hhcGUoYTogW251bWJlciwgbnVtYmVyXSwgYjogW251bWJlciwgbnVtYmVyXSk6IFtudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBhWzFdICE9PSBiWzBdID8gdW5kZWZpbmVkIDogW2FbMF0sIGJbMV1dO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBCcm9hZGNhc3RVdGlsIHtcbiAgLyoqXG4gICAqIENhbGN1bGF0ZSB0aGUgZXhwZWN0ZWQgc2hhcGUgd2hlbiBicm9hZGNhc3RpbmcgMiB0ZW5zb3JzXG4gICAqIEBwYXJhbSBhIFRoZSBzaGFwZSBvZiB0ZW5zb3IgQS4gU2hvdWxkIGJlIGFuIGFycmF5IG9mIHBvc2l0aXZlIGludGVnZXJzXG4gICAqIEBwYXJhbSBiIFRoZSBzaGFwZSBvZiB0ZW5zb3IgQi4gU2hvdWxkIGJlIGFuIGFycmF5IG9mIHBvc2l0aXZlIGludGVnZXJzXG4gICAqIEBwYXJhbSBpc01hdE11bCBXaGV0aGVyIHRoZSBvcGVyYXRpb24gaXMgTWF0TXVsXG4gICAqIEByZXR1cm5zIFRoZSBleHBlY3RlZCBzaGFwZSBvZiB0aGUgcmVzdWx0LCBvciB1bmRlZmluZWQgaWYgTi9BXG4gICAqL1xuICBzdGF0aWMgY2FsY1NoYXBlKFxuICAgIGFkaW1zOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBiZGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgaXNNYXRNdWwgPSBmYWxzZSxcbiAgKTogcmVhZG9ubHkgbnVtYmVyW10gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGFyYW5rID0gYWRpbXMubGVuZ3RoO1xuICAgIGNvbnN0IGJyYW5rID0gYmRpbXMubGVuZ3RoO1xuICAgIGlmIChhcmFuayA9PT0gMCkge1xuICAgICAgcmV0dXJuIGJkaW1zO1xuICAgIH1cbiAgICBpZiAoYnJhbmsgPT09IDApIHtcbiAgICAgIHJldHVybiBhZGltcztcbiAgICB9XG4gICAgY29uc3QgY3JhbmsgPSBNYXRoLm1heChhZGltcy5sZW5ndGgsIGJkaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgY2RpbXMgPSBuZXcgQXJyYXk8bnVtYmVyPihjcmFuayk7XG5cbiAgICAvLyBjYWxjdWxhdGUgdGhlIGxhc3QgMiBkaW1lbnNpb24gaWYgaXQgaXMgTWF0TXVsXG4gICAgaWYgKGlzTWF0TXVsKSB7XG4gICAgICBpZiAoYXJhbmsgPCAyIHx8IGJyYW5rIDwgMikge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgY29uc3QgY1NoYXBlTWF0TXVsID0gTWF0TXVsVXRpbC5jYWxjTWF0TXVsU2hhcGUoXG4gICAgICAgIFthZGltc1thcmFuayAtIDJdLCBhZGltc1thcmFuayAtIDFdXSxcbiAgICAgICAgW2JkaW1zW2JyYW5rIC0gMl0sIGJkaW1zW2JyYW5rIC0gMV1dLFxuICAgICAgKTtcbiAgICAgIGlmIChjU2hhcGVNYXRNdWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgW2NkaW1zW2NyYW5rIC0gMl0sIGNkaW1zW2NyYW5rIC0gMV1dID0gY1NoYXBlTWF0TXVsO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSBpc01hdE11bCA/IDMgOiAxOyBpIDw9IGNyYW5rOyBpKyspIHtcbiAgICAgIGNvbnN0IGFMZW4gPSBhcmFuayAtIGkgPCAwID8gMSA6IGFkaW1zW2FyYW5rIC0gaV07XG4gICAgICBjb25zdCBiTGVuID0gYnJhbmsgLSBpIDwgMCA/IDEgOiBiZGltc1ticmFuayAtIGldO1xuXG4gICAgICBpZiAoYUxlbiAhPT0gYkxlbiAmJiBhTGVuID4gMSAmJiBiTGVuID4gMSkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgY29uc3QgbWF4ID0gTWF0aC5tYXgoYUxlbiwgYkxlbik7XG4gICAgICBpZiAoYUxlbiAmJiBiTGVuKSB7XG4gICAgICAgIGNkaW1zW2NyYW5rIC0gaV0gPSBNYXRoLm1heChhTGVuLCBiTGVuKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHdoZW4gZWl0aGVyIGFMZW4gb3IgYkxlbiBpcyAwLCB0aGUgb3RoZXIgc2hvdWxkIGJlIGVpdGhlciAwIG9yIDEsIG90aGVyd2lzZSBpdCBpcyBub3QgYnJvYWRjYXN0YWJsZS5cbiAgICAgICAgaWYgKG1heCA+IDEpIHtcbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIGNkaW1zW2NyYW5rIC0gaV0gPSAwO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjZGltcztcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmUgaWYgYSBzaGFwZSBpcyB1bmlkaXJlY3Rpb25hbCBicm9hZGNhc3RhYmxlIHRvIGFub3RoZXIgc2hhcGVcbiAgICogQHBhcmFtIHNoYXBlIFRoZSBpbnB1dCBzaGFwZVxuICAgKiBAcGFyYW0gZmluYWxTaGFwZSBUaGUgZGVzaXJlZCBzaGFwZSBhZnRlciBicm9hZGNhc3RpbmdcbiAgICovXG4gIHN0YXRpYyBpc1ZhbGlkQnJvYWRjYXN0KHNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgZmluYWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pOiBib29sZWFuIHtcbiAgICAvLyBhbGlnbiBzaGFwZSB0byB0aGUgcmlnaHRcbiAgICBjb25zdCBpbnB1dFJhbmsgPSBzaGFwZS5sZW5ndGg7XG4gICAgY29uc3QgZmluYWxSYW5rID0gZmluYWxTaGFwZS5sZW5ndGg7XG4gICAgaWYgKGlucHV0UmFuayA+IGZpbmFsUmFuaykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmb3IgKGxldCBpID0gMTsgaSA8PSBpbnB1dFJhbms7IGkrKykge1xuICAgICAgaWYgKHNoYXBlW2lucHV0UmFuayAtIGldICE9PSAxICYmIHNoYXBlW2lucHV0UmFuayAtIGldICE9PSBmaW5hbFNoYXBlW2ZpbmFsUmFuayAtIGldKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFNoYXBlVXRpbCB7XG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIHNpemUgKG51bWJlciBvZiBlbGVtZW50cylcbiAgICovXG4gIHN0YXRpYyBzaXplKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogbnVtYmVyIHtcbiAgICByZXR1cm4gU2hhcGVVdGlsLmdldFNpemVGcm9tRGltZW5zaW9uUmFuZ2UoZGltcywgMCwgZGltcy5sZW5ndGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIGNvbnZlcnQgZGltcyBjb3JyZXNwb25kaW5nIHRvIHR5cGUgY2hhbmdlIHRvIHBhY2suIGV4LiB1aW50OCBkYXRhIHRvIHVpbnQzMlxuICAgKi9cbiAgc3RhdGljIGNvbnZlcnRTaGFwZShkaW1zOiByZWFkb25seSBudW1iZXJbXSwgc2l6ZSA9IDQpOiByZWFkb25seSBudW1iZXJbXSB7XG4gICAgY29uc3QgcmFuayA9IGRpbXMubGVuZ3RoO1xuICAgIGlmIChyYW5rID09PSAwKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGNvbnN0IG5ld0RpbXMgPSBuZXcgQXJyYXkocmFuayk7XG4gICAgbGV0IGkgPSByYW5rIC0gMTtcbiAgICB3aGlsZSAoaSA+PSAwKSB7XG4gICAgICBpZiAoZGltc1tpXSAlIHNpemUgPT09IDApIHtcbiAgICAgICAgbmV3RGltc1tpXSA9IGRpbXNbaV0gLyBzaXplO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGlmIChzaXplICUgZGltc1tpXSAhPT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBjb252ZXJ0IHNoYXBlJyk7XG4gICAgICB9XG4gICAgICBuZXdEaW1zW2ldID0gMTtcbiAgICAgIHNpemUgLz0gZGltc1tpXTtcbiAgICAgIGktLTtcbiAgICB9XG4gICAgZm9yIChpLS07IGkgPj0gMDsgaS0tKSB7XG4gICAgICBuZXdEaW1zW2ldID0gZGltc1tpXTtcbiAgICB9XG4gICAgcmV0dXJuIG5ld0RpbXM7XG4gIH1cblxuICAvKipcbiAgICogY2FsY3VsYXRlIHRoZSBzaXplIChudW1iZXIgb2YgZWxlbWVudHMpIGZyb20gdGhlIGdpdmVuIGF4aXMgKGluY2x1c2l2ZSlcbiAgICovXG4gIHN0YXRpYyBzaXplRnJvbURpbWVuc2lvbihkaW1zOiByZWFkb25seSBudW1iZXJbXSwgYXhpczogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAoYXhpcyA8IDAgfHwgYXhpcyA+IGRpbXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgZGltZW5zaW9uIG9mICR7YXhpc30gZm9yIHNpemVGcm9tRGltZW5zaW9uIGFzIFRlbnNvciBoYXMgJHtkaW1zLmxlbmd0aH0gZGltZW5zaW9ucy5gKTtcbiAgICB9XG4gICAgcmV0dXJuIFNoYXBlVXRpbC5nZXRTaXplRnJvbURpbWVuc2lvblJhbmdlKGRpbXMsIGF4aXMsIGRpbXMubGVuZ3RoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIHNpemUgKG51bWJlciBvZiBlbGVtZW50cykgdG8gdGhlIGdpdmVuIGF4aXMgKGV4Y2x1c2l2ZSlcbiAgICovXG4gIHN0YXRpYyBzaXplVG9EaW1lbnNpb24oZGltczogcmVhZG9ubHkgbnVtYmVyW10sIGF4aXM6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKGF4aXMgPCAwIHx8IGF4aXMgPiBkaW1zLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGRpbWVuc2lvbiBvZiAke2F4aXN9IGZvciBzaXplVG9EaW1lbnNpb24gYXMgVGVuc29yIGhhcyAke2RpbXMubGVuZ3RofSBkaW1lbnNpb25zLmApO1xuICAgIH1cbiAgICByZXR1cm4gU2hhcGVVdGlsLmdldFNpemVGcm9tRGltZW5zaW9uUmFuZ2UoZGltcywgMCwgYXhpcyk7XG4gIH1cblxuICAvKipcbiAgICogY2FsY3VsYXRlIHRoZSBzaXplIChudW1iZXIgb2YgZWxlbWVudHMpIGZyb20gYW5kIHRvIHRoZSBnaXZlbiBheGlzIFtzdGFydCwgZW5kKVxuICAgKi9cbiAgc3RhdGljIGdldFNpemVGcm9tRGltZW5zaW9uUmFuZ2UoZGltczogcmVhZG9ubHkgbnVtYmVyW10sIHN0YXJ0OiBudW1iZXIsIGVuZDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBsZXQgc2l6ZSA9IDE7XG4gICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICAgIC8vIHNhZmV0eSBjaGVjayBhcyB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgYnkgbXVsdGlwbGUgb3RoZXIgbWV0aG9kcyByZXF1aXJpbmcgc2l6ZS5cbiAgICAgIC8vIHNpemUgY2Fubm90IGJlIG5lZ2F0aXZlLlxuICAgICAgaWYgKGRpbXNbaV0gPCAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuICAgICAgICAgICdjYW5ub3QgZ2V0IHZhbGlkIHNpemUgZnJvbSBzcGVjaWZpZWQgZGltZW5zaW9uIHJhbmdlLiBNb3N0IGxpa2VseSB0aGUgcmFuZ2UgY29udGFpbnMgbmVnYXRpdmUgdmFsdWVzIGluIHRoZW0uJyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHNpemUgKj0gTnVtYmVyKGRpbXNbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gc2l6ZTtcbiAgfVxuXG4gIHN0YXRpYyBjb21wdXRlU3RyaWRlcyhkaW1zOiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBjb25zdCByYW5rID0gZGltcy5sZW5ndGg7XG4gICAgaWYgKHJhbmsgPT09IDApIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9IGVsc2UgaWYgKHJhbmsgPT09IDEpIHtcbiAgICAgIHJldHVybiBbMV07XG4gICAgfVxuICAgIGNvbnN0IHN0cmlkZXMgPSBuZXcgQXJyYXkocmFuayk7XG4gICAgc3RyaWRlc1tyYW5rIC0gMV0gPSAxO1xuICAgIHN0cmlkZXNbcmFuayAtIDJdID0gZGltc1tyYW5rIC0gMV07XG4gICAgZm9yIChsZXQgaSA9IHJhbmsgLSAzOyBpID49IDA7IC0taSkge1xuICAgICAgc3RyaWRlc1tpXSA9IHN0cmlkZXNbaSArIDFdICogZGltc1tpICsgMV07XG4gICAgfVxuICAgIHJldHVybiBzdHJpZGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIG5vcm1haWx6ZSBheGlzIG9mIHJhbmdlIFstciwgcikgaW50byBbMCwgcikuXG4gICAqL1xuICBzdGF0aWMgbm9ybWFsaXplQXhpcyhheGlzOiBudW1iZXIsIHRlbnNvclJhbms6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKGF4aXMgPCAtdGVuc29yUmFuayAmJiBheGlzID49IHRlbnNvclJhbmspIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndW5zdXBwb3J0ZWQgYXhpcyBmb3IgdGhpcyBvcGVyYXRpb24uJyk7XG4gICAgfVxuICAgIHJldHVybiBheGlzIDwgMCA/IGF4aXMgKyB0ZW5zb3JSYW5rIDogYXhpcztcbiAgfVxuXG4gIHN0YXRpYyBub3JtYWxpemVBeGVzKGF4ZXM6IHJlYWRvbmx5IG51bWJlcltdLCB0ZW5zb3JSYW5rPzogbnVtYmVyKTogbnVtYmVyW10ge1xuICAgIHJldHVybiBheGVzLm1hcCgoeCkgPT4gdGhpcy5ub3JtYWxpemVBeGlzKHgsIHRlbnNvclJhbmsgPz8gYXhlcy5sZW5ndGgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTb3J0cyBhIGdpdmVuIGFycmF5IGJhc2VkIG9uIHRoZSBpbmRpY2VzIGluIHRoZSBQZXJtIGFycmF5XG4gICAqIFVzZWQgaW4gVHJhbnNwb3NlXG4gICAqIEBwYXJhbSBhIEFycmF5IHRvIGJlIHNvcnRlZCBzdWNoIGFzIGRpbXMgb3Igc3RyaWRlc1xuICAgKiBAcGFyYW0gcGVybSBQZXJtIGdpdmVuOyBpZiBudWxsIGEgd2lsbCBiZSByZXZlcnNlZFxuICAgKi9cbiAgc3RhdGljIHNvcnRCYXNlZE9uUGVybShhOiByZWFkb25seSBudW1iZXJbXSwgcGVybT86IHJlYWRvbmx5IG51bWJlcltdKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGlmIChwZXJtKSB7XG4gICAgICByZXR1cm4gcGVybS5tYXAoKHYpID0+IGFbdl0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYS5zbGljZSgpLnJldmVyc2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGFkcyBhIGdpdmVuIHNoYXBlIGFjY29yZGluZyB0byB0aGUgcGFkZGluZyB2YWx1ZXNcbiAgICogQHBhcmFtIGRpbXMgc2hhcGUgb2YgdGhlIFRlbnNvciB0byBiZSBwYWRkZWRcbiAgICogQHBhcmFtIHBhZCBwYWQgdmFsdWVzXG4gICAqL1xuICBzdGF0aWMgcGFkU2hhcGUoZGltczogcmVhZG9ubHkgbnVtYmVyW10sIHBhZDogcmVhZG9ubHkgbnVtYmVyW10pOiByZWFkb25seSBudW1iZXJbXSB7XG4gICAgY29uc3QgcmFuayA9IGRpbXMubGVuZ3RoO1xuICAgIHJldHVybiBkaW1zLm1hcCgodiwgaSkgPT4gdiArIHBhZFtpXSArIHBhZFtpICsgcmFua10pO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgaWYgdGhlIHR3byBzaGFwZXMgYXJlIGlkZW50aWNhbFxuICAgKiBAcGFyYW0gc2hhcGUxXG4gICAqIEBwYXJhbSBzaGFwZTJcbiAgICovXG4gIHN0YXRpYyBhcmVFcXVhbChzaGFwZTE6IHJlYWRvbmx5IG51bWJlcltdLCBzaGFwZTI6IHJlYWRvbmx5IG51bWJlcltdKTogYm9vbGVhbiB7XG4gICAgaWYgKHNoYXBlMS5sZW5ndGggIT09IHNoYXBlMi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHNoYXBlMS5ldmVyeSgodiwgaSkgPT4gdiA9PT0gc2hhcGUyW2ldKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUG9vbENvbnZVdGlsIHtcbiAgLyoqXG4gICAqIEFkanVzdCB0aGUga2VybmVsLCBzdHJpZGVzLCBwYWRzIHRvIGNvcnJlY3QgcmFuay4gU2V0IHRvIGRlZmF1bHQgdmFsdWUgaWYgbm90IHByZXNlbnRcbiAgICogQHBhcmFtIGlzR2xvYmFsT3BlcmF0b3IgSWYgdHJ1ZSwgcGVyZm9ybSBnbG9iYWwgcG9vbGluZy5cbiAgICogQHBhcmFtIGlucHV0RGltcyBUaGUgaW5wdXQgdGVuc29yIGRpbWVuc2lvbi5cbiAgICogQHBhcmFtIGtlcm5lbFNoYXBlIFRoZSBzaXplIG9mIHRoZSBrZXJuZWwgYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0gc3RyaWRlcyBTdHJpZGUgYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0gZGlsYXRpb25zIERpbGF0aW9uIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIHBhZHMgUGFkZGluZyBmb3IgdGhlIGJlZ2lubmluZyBhbmQgZW5kaW5nIGFsb25nIGVhY2ggYXhpcy5cbiAgICovXG4gIHN0YXRpYyBhZGp1c3RQb29sQXR0cmlidXRlcyhcbiAgICBpc0dsb2JhbE9wZXJhdG9yOiBib29sZWFuLFxuICAgIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAga2VybmVsU2hhcGU6IG51bWJlcltdLFxuICAgIHN0cmlkZXM6IG51bWJlcltdLFxuICAgIGRpbGF0aW9uczogbnVtYmVyW10sXG4gICAgcGFkczogbnVtYmVyW10sXG4gICk6IHZvaWQge1xuICAgIGlmICghaXNHbG9iYWxPcGVyYXRvciAmJiBrZXJuZWxTaGFwZS5sZW5ndGggIT09IGlucHV0RGltcy5sZW5ndGggLSAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2xlbmd0aCBvZiBzcGVjaWZpZWQga2VybmVsIHNoYXBlcyBzaG91bGQgYmUgMiBsZXNzIHRoYW4gbGVuZ3RoIG9mIGlucHV0IGRpbWVuc2lvbnMnKTtcbiAgICB9XG5cbiAgICBpZiAoaXNHbG9iYWxPcGVyYXRvcikge1xuICAgICAgLy8gYWRqdXN0IGtlcm5lbCBzaGFwZSB0byBjb3ZlciB0aGUgaW5wdXQgZGltc1xuICAgICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwgaW5wdXREaW1zLmxlbmd0aCAtIDI7IGRpbSsrKSB7XG4gICAgICAgIGlmIChkaW0gPj0ga2VybmVsU2hhcGUubGVuZ3RoKSB7XG4gICAgICAgICAga2VybmVsU2hhcGUucHVzaChpbnB1dERpbXNbZGltICsgMl0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGtlcm5lbFNoYXBlW2RpbV0gPSBpbnB1dERpbXNbZGltICsgMl07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBhZGp1c3Qgc3RyaWRlcyBsZW5ndGggdG8gbWF0Y2gga2VybmVsIHNoYXBlIGxlbmd0aFxuICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGtlcm5lbFNoYXBlLmxlbmd0aDsgZGltKyspIHtcbiAgICAgIGlmIChkaW0gPCBzdHJpZGVzLmxlbmd0aCkge1xuICAgICAgICBpZiAoc3RyaWRlc1tkaW1dIDwgMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignc3RyaWRlcyBzaG91bGQgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RyaWRlcy5wdXNoKDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFkanVzdCBkaWxhdGlvbiB2YWx1ZVxuICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGtlcm5lbFNoYXBlLmxlbmd0aDsgZGltKyspIHtcbiAgICAgIGlmIChkaW0gPCBkaWxhdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgIGlmIChkaWxhdGlvbnNbZGltXSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RpbGF0aW9ucyBzaG91bGQgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGlsYXRpb25zLnB1c2goMSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gYWRqdXN0IHBhZHMgbGVuZ3RoIHRvIG1hdGNoIDIgKiBrZXJuZWwgc2hhcGUgbGVuZ3RoXG4gICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwga2VybmVsU2hhcGUubGVuZ3RoICogMjsgZGltKyspIHtcbiAgICAgIGlmIChkaW0gPCBwYWRzLmxlbmd0aCkge1xuICAgICAgICBpZiAocGFkc1tkaW1dIDwgMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncGFkIHNob3VsZCBiZSBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gMScpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwYWRzLnB1c2goMCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gc2FuaXR5IGNoZWNrcyBmb3IgdmFsdWVzIGluIGtlcm5lbCBzaGFwZXMgYW5kIHBhZHNcbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBrZXJuZWxTaGFwZS5sZW5ndGg7IGRpbSsrKSB7XG4gICAgICBpZiAoa2VybmVsU2hhcGVbZGltXSA8PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigna2VybmVsIHNoYXBlcyBuZWVkIHRvIGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYWRzW2RpbV0gPj0ga2VybmVsU2hhcGVbZGltXSB8fCBwYWRzW2RpbSArIGtlcm5lbFNoYXBlLmxlbmd0aF0gPj0ga2VybmVsU2hhcGVbZGltXSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhZHMgc2hvdWxkIGJlIHNtYWxsZXIgdGhhbiBrZXJuZWwnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBhZGp1c3QgcGFkIHZhbHVlcyBiYXNlZCBvbiAnYXV0b1BhZCcgYXR0cmlidXRlXG4gIHN0YXRpYyBhZGp1c3RQYWRzQmFzZWRPbkF1dG9QYWQoXG4gICAgaW5wdXREaW1zOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBkaWxhdGlvbnM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGtlcm5lbFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBwYWRzOiBudW1iZXJbXSxcbiAgICBpc0NoYW5uZWxMYXN0OiBib29sZWFuLFxuICAgIGF1dG9QYWQ/OiBzdHJpbmcsXG4gICk6IHZvaWQge1xuICAgIGlmICghYXV0b1BhZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChwYWRzLmxlbmd0aCAhPT0gMiAqIChpbnB1dERpbXMubGVuZ3RoIC0gMikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbGVuZ3RoIG9mIHBhZHMgc2hvdWxkIGJlIHR3aWNlIHRoZSBsZW5ndGggb2YgZGF0YSBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgaWYgKHN0cmlkZXMubGVuZ3RoICE9PSBpbnB1dERpbXMubGVuZ3RoIC0gMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdsZW5ndGggb2Ygc3RyaWRlcyBzaG91bGQgYmUgdGhlIGxlbmd0aCBvZiBkYXRhIGRpbWVuc2lvbnMnKTtcbiAgICB9XG5cbiAgICBpZiAoa2VybmVsU2hhcGUubGVuZ3RoICE9PSBpbnB1dERpbXMubGVuZ3RoIC0gMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdsZW5ndGggb2Yga2VybmVsIHNoYXBlcyBzaG91bGQgYmUgdGhlIGxlbmd0aCBvZiBkYXRhIGRpbWVuc2lvbnMnKTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBpbnB1dERpbXMubGVuZ3RoIC0gMjsgZGltKyspIHtcbiAgICAgIFBvb2xDb252VXRpbC5hZGp1c3RQYWRBbmRSZXR1cm5TaGFwZShcbiAgICAgICAgaW5wdXREaW1zW2RpbSArIChpc0NoYW5uZWxMYXN0ID8gMSA6IDIpXSxcbiAgICAgICAgc3RyaWRlc1tkaW1dLFxuICAgICAgICBkaWxhdGlvbnNbZGltXSxcbiAgICAgICAga2VybmVsU2hhcGVbZGltXSxcbiAgICAgICAgcGFkcyxcbiAgICAgICAgZGltLFxuICAgICAgICBkaW0gKyBpbnB1dERpbXMubGVuZ3RoIC0gMixcbiAgICAgICAgYXV0b1BhZCxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZSB0aGUgb3V0cHV0IHNoYXBlIGZvciBQb29sIG9wcyBiYXNlZCBvbiBpbnB1dCBhdHRyaWJ1dGVzLiAoU2hvdWxkIGJlIHVzZWQgb25seSBmb3IgUG9vbCBvcHMpXG4gICAqIEBwYXJhbSBpc0dsb2JhbE9wZXJhdG9yIElmIHRydWUsIHBlcmZvcm0gZ2xvYmFsIHBvb2xpbmcuXG4gICAqIEBwYXJhbSBpbnB1dERpbXMgVGhlIGlucHV0IHRlbnNvciBkaW1lbnNpb24uIChpbnB1dHNbMF0uZGltcylcbiAgICogQHBhcmFtIHN0cmlkZXMgU3RyaWRlIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGRpbGF0aW9ucyBEaWxhdGlvbiBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBrZXJuZWxTaGFwZSBUaGUgc2l6ZSBvZiB0aGUga2VybmVsIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIHBhZHMgUGFkZGluZyBmb3IgdGhlIGJlZ2lubmluZyBhbmQgZW5kaW5nIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGF1dG9QYWQgREVQUkVDQVRFRCBhdHRyaWJ1dGUgc3VwcG9ydGVkIGZvciBsZWdhY3kgbW9kZWxzLiBTcGVjaWZpZXMgaG93IHRvIGltcGxpY2l0bHkgY2FsY3VsYXRlIHBhZHMgaW4gZWFjaFxuICAgKiAgICAgZGltZW5zaW9uLiBDYW4gdGFrZSB2YWx1ZXMgTk9UU0VULCBTQU1FX1VQUEVSLCBTQU1FX0xPV0VSLCBvciBWQUxJRC5cbiAgICovXG4gIHN0YXRpYyBjb21wdXRlUG9vbE91dHB1dFNoYXBlKFxuICAgIGlzR2xvYmFsT3BlcmF0b3I6IGJvb2xlYW4sXG4gICAgaW5wdXREaW1zOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBzdHJpZGVzOiBudW1iZXJbXSxcbiAgICBkaWxhdGlvbnM6IG51bWJlcltdLFxuICAgIGtlcm5lbFNoYXBlOiBudW1iZXJbXSxcbiAgICBwYWRzOiBudW1iZXJbXSxcbiAgICBhdXRvUGFkPzogc3RyaW5nLFxuICApOiBudW1iZXJbXSB7XG4gICAgaWYgKGlucHV0RGltcy5sZW5ndGggPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCBzaGFwZSBtdXN0IGJlIG9mIHNpemUgZ3JlYXRlciB0aGFuIDAnKTtcbiAgICB9XG5cbiAgICAvLyBBZGQgYmF0Y2ggc2l6ZSBhbmQgbnVtYmVyIG9mIGNoYW5uZWxzIG9mIG91dHB1dFxuICAgIGNvbnN0IG91dHB1dERpbXMgPSBbaW5wdXREaW1zWzBdLCBpbnB1dERpbXNbMV1dO1xuXG4gICAgUG9vbENvbnZVdGlsLmNvbXB1dGVTaGFwZUhlbHBlcihcbiAgICAgIGlzR2xvYmFsT3BlcmF0b3IsXG4gICAgICBpbnB1dERpbXMsXG4gICAgICBvdXRwdXREaW1zLFxuICAgICAgc3RyaWRlcyxcbiAgICAgIGRpbGF0aW9ucyxcbiAgICAgIGtlcm5lbFNoYXBlLFxuICAgICAgcGFkcyxcbiAgICAgIGF1dG9QYWQsXG4gICAgKTtcbiAgICByZXR1cm4gb3V0cHV0RGltcztcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIG91dHB1dCBzaGFwZSBmb3IgQ29udiBvcCBiYXNlZCBvbiBpbnB1dCBhdHRyaWJ1dGVzLiAoU2hvdWxkIGJlIHVzZWQgb25seSBmb3IgQ29udiBvcClcbiAgICogQHBhcmFtIGlucHV0RGltcyBUaGUgaW5wdXQgdGVuc29yIGRpbWVuc2lvbi4gKGlucHV0c1swXS5kaW1zKVxuICAgKiBAcGFyYW0gZmlsdGVyRGltcyBUaGUgZmlsdGVyIHRlbnNvciBkaW1lbnNpb24uIChpbnB1dHNbMV0uZGltcylcbiAgICogQHBhcmFtIHN0cmlkZXMgU3RyaWRlIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGtlcm5lbFNoYXBlIFRoZSBzaXplIG9mIHRoZSBrZXJuZWwgYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0gcGFkcyBQYWRkaW5nIGZvciB0aGUgYmVnaW5uaW5nIGFuZCBlbmRpbmcgYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0gYXV0b1BhZCBERVBSRUNBVEVEIGF0dHJpYnV0ZSBzdXBwb3J0ZWQgZm9yIGxlZ2FjeSBtb2RlbHMuIFNwZWNpZmllcyBob3cgdG8gaW1wbGljaXRseSBjYWxjdWxhdGUgcGFkcyBpbiBlYWNoXG4gICAqICAgICBkaW1lbnNpb24uIENhbiB0YWtlIHZhbHVlcyBOT1RTRVQsIFNBTUVfVVBQRVIsIFNBTUVfTE9XRVIsIG9yIFZBTElELlxuICAgKi9cbiAgc3RhdGljIGNvbXB1dGVDb252T3V0cHV0U2hhcGUoXG4gICAgaW5wdXREaW1zOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBmaWx0ZXJEaW1zOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBzdHJpZGVzOiBudW1iZXJbXSxcbiAgICBkaWxhdGlvbnM6IG51bWJlcltdLFxuICAgIGtlcm5lbFNoYXBlOiBudW1iZXJbXSxcbiAgICBwYWRzOiBudW1iZXJbXSxcbiAgICBhdXRvUGFkPzogc3RyaW5nLFxuICApOiBudW1iZXJbXSB7XG4gICAgaWYgKGlucHV0RGltcy5sZW5ndGggPD0gMCB8fCBmaWx0ZXJEaW1zLmxlbmd0aCA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgaW5wdXQgdGVuc29yIGRpbXMgb3IgaW52YWxpZCBmaWx0ZXIgdGVuc29yIGRpbXMnKTtcbiAgICB9XG5cbiAgICAvLyBBZGQgYmF0Y2ggc2l6ZSBhbmQgbnVtYmVyIG9mIGNoYW5uZWxzIG9mIG91dHB1dFxuICAgIGNvbnN0IG91dHB1dERpbXMgPSBbaW5wdXREaW1zWzBdLCBmaWx0ZXJEaW1zWzBdXTtcblxuICAgIFBvb2xDb252VXRpbC5jb21wdXRlU2hhcGVIZWxwZXIoZmFsc2UsIGlucHV0RGltcywgb3V0cHV0RGltcywgc3RyaWRlcywgZGlsYXRpb25zLCBrZXJuZWxTaGFwZSwgcGFkcywgYXV0b1BhZCk7XG4gICAgcmV0dXJuIG91dHB1dERpbXM7XG4gIH1cblxuICAvLyB3aWxsIGNvbXB1dGUgb3V0cHV0IHNoYXBlcyBmb3IgZGF0YSBkaW1lbnNpb25zIE9OTFkgKGkuZS4pIG5vIGJhdGNoIHNpemUgYW5kIGNoYW5uZWxzXG4gIC8vIGNhbGxlZCBieSBjb21wdXRlUG9vbE91dHB1dFNoYXBlKCkgYW5kIGNvbXB1dGVDb252T3V0cHV0U2hhcGUoKVxuICAvLyBhZGp1c3QgcGFkcyBiYXNlZCBvbiAnYXV0b1BhZCcgYXR0cmlidXRlIHByaW9yIHRvIHNoYXBlIGNvbXB1dGF0aW9uXG4gIHByaXZhdGUgc3RhdGljIGNvbXB1dGVTaGFwZUhlbHBlcihcbiAgICBpc0dsb2JhbE9wZXJhdG9yOiBib29sZWFuLFxuICAgIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgb3V0cHV0RGltczogbnVtYmVyW10sXG4gICAgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgZGlsYXRpb25zOiByZWFkb25seSBudW1iZXJbXSxcbiAgICBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgcGFkczogbnVtYmVyW10sXG4gICAgYXV0b1BhZD86IHN0cmluZyxcbiAgKSB7XG4gICAgaWYgKGlzR2xvYmFsT3BlcmF0b3IpIHtcbiAgICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGlucHV0RGltcy5sZW5ndGggLSAyOyBkaW0rKykge1xuICAgICAgICBvdXRwdXREaW1zLnB1c2goMSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGlucHV0RGltcy5sZW5ndGggLSAyOyBkaW0rKykge1xuICAgICAgICBvdXRwdXREaW1zLnB1c2goXG4gICAgICAgICAgUG9vbENvbnZVdGlsLmFkanVzdFBhZEFuZFJldHVyblNoYXBlKFxuICAgICAgICAgICAgaW5wdXREaW1zW2RpbSArIDJdLFxuICAgICAgICAgICAgc3RyaWRlc1tkaW1dLFxuICAgICAgICAgICAgZGlsYXRpb25zW2RpbV0sXG4gICAgICAgICAgICBrZXJuZWxTaGFwZVtkaW1dLFxuICAgICAgICAgICAgcGFkcyxcbiAgICAgICAgICAgIGRpbSxcbiAgICAgICAgICAgIGRpbSArIGlucHV0RGltcy5sZW5ndGggLSAyLFxuICAgICAgICAgICAgYXV0b1BhZCxcbiAgICAgICAgICApLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIGhlbHBlciBmb3IgY29tcHV0ZVNoYXBlSGVscGVyKCkgYW5kIGFkanVzdFBhZHNCYXNlZE9uQXV0b1BhZCgpXG4gIC8vIGFkanVzdHMgcGFkIHZhbHVlIGZvciBnaXZlbiAnYXV0b1BhZCcgc3RyaW5nIGFuZCBjb21wdXRlcyBvdXRwdXQgc2hhcGUgYWxvbmcgYSBwYXJ0aWN1bGFyIGRpbWVuc2lvblxuICBwcml2YXRlIHN0YXRpYyBhZGp1c3RQYWRBbmRSZXR1cm5TaGFwZShcbiAgICBpblNpemU6IG51bWJlcixcbiAgICBzdHJpZGU6IG51bWJlcixcbiAgICBkaWxhdGlvbjogbnVtYmVyLFxuICAgIGtlcm5lbDogbnVtYmVyLFxuICAgIHBhZHM6IG51bWJlcltdLFxuICAgIHBhZEhlYWRJbmRleDogbnVtYmVyLFxuICAgIHBhZFRhaWxJbmRleDogbnVtYmVyLFxuICAgIGF1dG9QYWQ/OiBzdHJpbmcsXG4gICk6IG51bWJlciB7XG4gICAgY29uc3QgZGtlcm5lbCA9IGRpbGF0aW9uICogKGtlcm5lbCAtIDEpICsgMTtcbiAgICBpZiAoYXV0b1BhZCAmJiBhdXRvUGFkICE9PSAnTk9UU0VUJykge1xuICAgICAgc3dpdGNoIChhdXRvUGFkKSB7XG4gICAgICAgIGNhc2UgJ1ZBTElEJzpcbiAgICAgICAgICBwYWRzW3BhZEhlYWRJbmRleF0gPSAwO1xuICAgICAgICAgIHBhZHNbcGFkVGFpbEluZGV4XSA9IDA7XG4gICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGluU2l6ZSAtIGRrZXJuZWwpIC8gc3RyaWRlICsgMSk7XG4gICAgICAgIGNhc2UgJ1NBTUVfTE9XRVInOlxuICAgICAgICBjYXNlICdTQU1FX1VQUEVSJzpcbiAgICAgICAgICBpZiAoZGlsYXRpb24gIT09IDEpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRGlsYXRpb24gbm90IHN1cHBvcnRlZCBmb3IgU0FNRV9VUFBFUiBvciBTQU1FX0xPV0VSJyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGxlZ2FjeVRhcmdldFNpemUgPSAoaW5TaXplICsgc3RyaWRlIC0gMSkgLyBzdHJpZGU7XG4gICAgICAgICAgICBjb25zdCBwYWROZWVkZWQgPSAobGVnYWN5VGFyZ2V0U2l6ZSAtIDEpICogc3RyaWRlICsga2VybmVsIC0gaW5TaXplO1xuICAgICAgICAgICAgcGFkc1twYWRIZWFkSW5kZXhdID0gYXV0b1BhZCA9PT0gJ1NBTUVfTE9XRVInID8gTWF0aC5mbG9vcigocGFkTmVlZGVkICsgMSkgLyAyKSA6IE1hdGguZmxvb3IocGFkTmVlZGVkIC8gMik7XG4gICAgICAgICAgICBwYWRzW3BhZFRhaWxJbmRleF0gPSBwYWROZWVkZWQgLSBwYWRzW3BhZEhlYWRJbmRleF07XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcigoaW5TaXplICsgcGFkTmVlZGVkIC0ga2VybmVsKSAvIHN0cmlkZSArIDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIEF1dG9QYWQgdHlwZScpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gTWF0aC5mbG9vcigoaW5TaXplICsgcGFkc1twYWRIZWFkSW5kZXhdICsgcGFkc1twYWRUYWlsSW5kZXhdIC0gZGtlcm5lbCkgLyBzdHJpZGUgKyAxKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEdlbW1VdGlsIHtcbiAgLy8gd2lsbCBtYWtlIHN1cmUgaW5wdXQgc2hhcGVzIGFyZSBjb21wYXRpYmxlIGZvciB0aGlzIG9wXG4gIC8vIGFuZCByZXR1cm4gYmFjayB0aGUgc2hhcGUgb2YgdGhlIG91dHB1dCBpbiB0aGUgZm9ybSBvZiBhIHR1cGxlXG4gIC8vIHdpbGwgdGhyb3cgZXhjZXB0aW9uIGlmIHRoZSBpbnB1dCBzaGFwZXMgYXJlIG5vdCBjb21wYXRpYmxlXG4gIHN0YXRpYyBnZXRTaGFwZU9mR2VtbVJlc3VsdChcbiAgICBsZWZ0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIHRyYW5zTGVmdDogYm9vbGVhbixcbiAgICByaWdodFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgICB0cmFuc1JpZ2h0OiBib29sZWFuLFxuICAgIGJpYXNTaGFwZT86IHJlYWRvbmx5IG51bWJlcltdLFxuICApOiByZWFkb25seSBudW1iZXJbXSB7XG4gICAgaWYgKGxlZnRTaGFwZS5sZW5ndGggIT09IDIgfHwgcmlnaHRTaGFwZS5sZW5ndGggIT09IDIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc2hhcGUgbmVlZCB0byBiZSBvZiBzaXplIDInKTtcbiAgICB9XG5cbiAgICBsZXQgTTogbnVtYmVyO1xuICAgIGxldCBLOiBudW1iZXI7XG4gICAgbGV0IE46IG51bWJlcjtcblxuICAgIGlmICh0cmFuc0xlZnQpIHtcbiAgICAgIE0gPSBsZWZ0U2hhcGVbMV07XG4gICAgICBLID0gbGVmdFNoYXBlWzBdO1xuICAgIH0gZWxzZSB7XG4gICAgICBNID0gbGVmdFNoYXBlWzBdO1xuICAgICAgSyA9IGxlZnRTaGFwZVsxXTtcbiAgICB9XG5cbiAgICBsZXQga0RpbSA9IC0xO1xuXG4gICAgaWYgKHRyYW5zUmlnaHQpIHtcbiAgICAgIE4gPSByaWdodFNoYXBlWzBdO1xuICAgICAga0RpbSA9IDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIE4gPSByaWdodFNoYXBlWzFdO1xuICAgICAga0RpbSA9IDA7XG4gICAgfVxuXG4gICAgaWYgKHJpZ2h0U2hhcGVba0RpbV0gIT09IEspIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZGltZW5zaW9uIG1pc21hdGNoJyk7XG4gICAgfVxuXG4gICAgaWYgKE0gPD0gMCB8fCBOIDw9IDAgfHwgSyA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgc2hhcGUgc3BlY2lmaWVkJyk7XG4gICAgfVxuXG4gICAgaWYgKGJpYXNTaGFwZSAmJiAhQnJvYWRjYXN0VXRpbC5pc1ZhbGlkQnJvYWRjYXN0KGJpYXNTaGFwZSwgW00sIE5dKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdnZW1tOiBpbnZhbGlkIGJpYXMgc2hhcGUgZm9yIGJyb2FkY2FzdCcpO1xuICAgIH1cblxuICAgIHJldHVybiBbTSwgTiwgS107XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IE1JTl9DTElQID0gLTMuNDAyODIzNDY2Mzg1Mjg4NmUzODtcbmV4cG9ydCBjb25zdCBNQVhfQ0xJUCA9IDMuNDAyODIzNDY2Mzg1Mjg4NmUzODtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yIH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHsgdGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yIH0gZnJvbSAnLi4vd2FzbS1jb21tb24nO1xuXG5leHBvcnQgY29uc3QgY3JlYXRlVmlldyA9IChcbiAgZGF0YUJ1ZmZlcjogQXJyYXlCdWZmZXIsXG4gIHR5cGU6IFRlbnNvci5UeXBlLFxuKTpcbiAgfCBJbnQzMkFycmF5XG4gIHwgVWludDMyQXJyYXlcbiAgfCBCaWdJbnQ2NEFycmF5XG4gIHwgQmlnVWludDY0QXJyYXlcbiAgfCBVaW50OEFycmF5XG4gIHwgRmxvYXQzMkFycmF5XG4gIHwgRmxvYXQ2NEFycmF5XG4gIHwgSW50OEFycmF5XG4gIHwgSW50MTZBcnJheVxuICB8IFVpbnQxNkFycmF5ID0+IG5ldyAodGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yKHR5cGUpKShkYXRhQnVmZmVyKTtcblxuLyoqXG4gKiBhIFRlbnNvclZpZXcgZG9lcyBub3Qgb3duIHRoZSBkYXRhLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvclZpZXcge1xuICByZWFkb25seSBkYXRhOiBudW1iZXI7XG4gIHJlYWRvbmx5IGRhdGFUeXBlOiBudW1iZXI7XG4gIHJlYWRvbmx5IGRpbXM6IHJlYWRvbmx5IG51bWJlcltdO1xuXG4gIC8qKlxuICAgKiBnZXQgYSBGbG9hdDE2QXJyYXkgZGF0YSB2aWV3IG9mIHRoZSB0ZW5zb3IgZGF0YS4gdGVuc29yIGRhdGEgbXVzdCBiZSBvbiBDUFUuXG4gICAqL1xuICBnZXRVaW50MTZBcnJheSgpOiBVaW50MTZBcnJheTtcblxuICAvKipcbiAgICogZ2V0IGEgRmxvYXQzMkFycmF5IGRhdGEgdmlldyBvZiB0aGUgdGVuc29yIGRhdGEuIHRlbnNvciBkYXRhIG11c3QgYmUgb24gQ1BVLlxuICAgKi9cbiAgZ2V0RmxvYXQzMkFycmF5KCk6IEZsb2F0MzJBcnJheTtcblxuICAvKipcbiAgICogZ2V0IGEgQmlnSW50NjRBcnJheSBkYXRhIHZpZXcgb2YgdGhlIHRlbnNvciBkYXRhLiB0ZW5zb3IgZGF0YSBtdXN0IGJlIG9uIENQVS5cbiAgICovXG4gIGdldEJpZ0ludDY0QXJyYXkoKTogQmlnSW50NjRBcnJheTtcblxuICAvKipcbiAgICogZ2V0IGEgSW50MzJBcnJheSBkYXRhIHZpZXcgb2YgdGhlIHRlbnNvciBkYXRhLiB0ZW5zb3IgZGF0YSBtdXN0IGJlIG9uIENQVS5cbiAgICovXG4gIGdldEludDMyQXJyYXkoKTogSW50MzJBcnJheTtcblxuICAvKipcbiAgICogZ2V0IGEgVWludDE2QXJyYXkgZGF0YSB2aWV3IG9mIHRoZSB0ZW5zb3IgZGF0YS4gdGVuc29yIGRhdGEgbXVzdCBiZSBvbiBDUFUuXG4gICAqL1xuICBnZXRVaW50MTZBcnJheSgpOiBVaW50MTZBcnJheTtcblxuICAvKipcbiAgICogY3JlYXRlIGEgbmV3IHRlbnNvciB2aWV3IHdpdGggdGhlIHNhbWUgZGF0YSBidXQgZGlmZmVyZW50IGRpbWVuc2lvbnMuXG4gICAqL1xuICByZXNoYXBlKG5ld0RpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogVGVuc29yVmlldztcbn1cbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgV2ViTk5CYWNrZW5kIH0gZnJvbSAnLi4vYmFja2VuZC13ZWJubic7XG5pbXBvcnQgeyB0ZW5zb3JUeXBlVG9UeXBlZEFycmF5Q29uc3RydWN0b3IgfSBmcm9tICcuLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBMT0dfREVCVUcgfSBmcm9tICcuLi9sb2cnO1xuXG4vLyBXZWJOTiBBUEkgY3VycmVudGx5IGRvZXMgbm90IGhhdmUgYSBUeXBlU2NyaXB0IGRlZmluaXRpb24gZmlsZS4gVGhpcyBmaWxlIGlzIGEgd29ya2Fyb3VuZCB3aXRoIHR5cGVzIGdlbmVyYXRlZCBmcm9tXG4vLyBXZWJOTiBBUEkgc3BlY2lmaWNhdGlvbi5cbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS93ZWJtYWNoaW5lbGVhcm5pbmcvd2Vibm4vaXNzdWVzLzY3N1xuLy8vIDxyZWZlcmVuY2UgcGF0aD1cIndlYm5uLmQudHNcIiAvPlxuXG4vKipcbiAqIE1hcCBmcm9tIE1MT3BlcmFuZERhdGFUeXBlIHRvIHNpemUgaW4gYml0cy4gVXNpbmcgYml0cyBpbnN0ZWFkIG9mIGJ5dGVzIHRvIGF2b2lkIHBvc3NpYmxlIHByZWNpc2lvbiBsb3NzIG9uIGludDQgYW5kIHVpbnQ0LlxuICovXG5jb25zdCB3ZWJubkRhdGFUeXBlVG9TaXplID0gbmV3IE1hcDxNTE9wZXJhbmREYXRhVHlwZSwgbnVtYmVyPihbXG4gIFsnZmxvYXQzMicsIDMyXSxcbiAgWydmbG9hdDE2JywgMTZdLFxuICBbJ2ludDMyJywgMzJdLFxuICBbJ3VpbnQzMicsIDMyXSxcbiAgWydpbnQ2NCcsIDY0XSxcbiAgWyd1aW50NjQnLCA2NF0sXG4gIFsnaW50OCcsIDhdLFxuICBbJ3VpbnQ4JywgOF0sXG4gIFsnaW50NCcsIDRdLFxuICBbJ3VpbnQ0JywgNF0sXG5dKTtcblxuLy8gQ29udmVydCBpbnRlZ2VyIGRhdGEgdG8gYW4gSW50MzJBcnJheSBidWZmZXIuXG4vLyBTdXBwb3J0cyBjb252ZXJzaW9uIGZyb20gaW50NjQsIHVpbnQ2NCwgdWludDMyLCBpbnQ4IGFuZCB1aW50OCB0byBpbnQzMi5cbmV4cG9ydCBjb25zdCBjb252ZXJ0RGF0YVRvSW50MzIgPSAoZGF0YTogVWludDhBcnJheSwgZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlKTogVWludDhBcnJheSA9PiB7XG4gIGlmIChkYXRhVHlwZSA9PT0gJ2ludDMyJykge1xuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgY29uc3QgZGF0YVR5cGVTaXplID0gd2Vibm5EYXRhVHlwZVRvU2l6ZS5nZXQoZGF0YVR5cGUpO1xuICBpZiAoIWRhdGFUeXBlU2l6ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgV2ViTk4gYmFja2VuZCBkb2VzIG5vdCBzdXBwb3J0IGRhdGEgdHlwZTogJHtkYXRhVHlwZX1gKTtcbiAgfVxuICBjb25zdCBieXRlc1BlckVsZW1lbnQgPSBkYXRhVHlwZVNpemUgLyA4O1xuICAvLyBNYWtlIHN1cmUgdGhlIGRhdGEgbGVuZ3RoIGlzIGEgbXVsdGlwbGUgb2YgdGhlIGRhdGEgdHlwZSBzaXplLlxuICBpZiAoZGF0YS5ieXRlTGVuZ3RoICUgYnl0ZXNQZXJFbGVtZW50ICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIFVpbnQ4QXJyYXkgbGVuZ3RoIC0gbXVzdCBiZSBhIG11bHRpcGxlIG9mICR7Ynl0ZXNQZXJFbGVtZW50fS5gKTtcbiAgfVxuXG4gIC8vIENvbnZlcnQgVWludDhBcnJheSB0byBvcmlnaW5hbCB0eXBlZCBhcnJheS5cbiAgY29uc3QgbnVtRWxlbWVudHMgPSBkYXRhLmJ5dGVMZW5ndGggLyBieXRlc1BlckVsZW1lbnQ7XG4gIGNvbnN0IG9yaWdpbmFsQXJyYXkgPSBuZXcgKHRlbnNvclR5cGVUb1R5cGVkQXJyYXlDb25zdHJ1Y3RvcihkYXRhVHlwZSkpKGRhdGEuYnVmZmVyLCBkYXRhLmJ5dGVPZmZzZXQsIG51bUVsZW1lbnRzKTtcblxuICBzd2l0Y2ggKGRhdGFUeXBlKSB7XG4gICAgY2FzZSAnaW50NjQnOlxuICAgIGNhc2UgJ3VpbnQ2NCc6IHtcbiAgICAgIC8vIENvbnZlcnQgb3JpZ2luYWwgdHlwZWQgYXJyYXkgdG8gSW50MzJBcnJheS5cbiAgICAgIGNvbnN0IGludDMyQXJyYXkgPSBuZXcgSW50MzJBcnJheShudW1FbGVtZW50cyk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUVsZW1lbnRzOyBpKyspIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBvcmlnaW5hbEFycmF5W2ldO1xuXG4gICAgICAgIC8vIENoZWNrIGZvciBvdmVyZmxvdy5cbiAgICAgICAgaWYgKHZhbHVlID4gMjE0NzQ4MzY0N24gfHwgdmFsdWUgPCAtMjE0NzQ4MzY0OG4pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbiBub3QgY29udmVydCBpbnQ2NCBkYXRhIHRvIGludDMyIC0gdmFsdWUgb3V0IG9mIHJhbmdlLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaW50MzJBcnJheVtpXSA9IE51bWJlcih2YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShpbnQzMkFycmF5LmJ1ZmZlcik7XG4gICAgfVxuICAgIGNhc2UgJ2ludDgnOlxuICAgIGNhc2UgJ3VpbnQ4JzpcbiAgICBjYXNlICd1aW50MzInOiB7XG4gICAgICAvLyBDaGVjayBmb3Igb3ZlcmZsb3cuXG4gICAgICBpZiAoZGF0YVR5cGUgPT09ICd1aW50MzInKSB7XG4gICAgICAgIGlmIChvcmlnaW5hbEFycmF5LnNvbWUoKHZhbHVlKSA9PiB2YWx1ZSA+IDIxNDc0ODM2NDcpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4gbm90IGNvbnZlcnQgdWludDMyIGRhdGEgdG8gaW50MzIgLSB2YWx1ZSBvdXQgb2YgcmFuZ2UuYCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIENvbnZlcnQgb3JpZ2luYWwgdHlwZWQgYXJyYXkgdG8gSW50MzJBcnJheS5cbiAgICAgIGNvbnN0IGludDMyQXJyYXkgPSBJbnQzMkFycmF5LmZyb20ob3JpZ2luYWxBcnJheSwgTnVtYmVyKTtcbiAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShpbnQzMkFycmF5LmJ1ZmZlcik7XG4gICAgfVxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGRhdGEgY29udmVyc2lvbiBmcm9tICR7ZGF0YVR5cGV9IHRvICdpbnQzMidgKTtcbiAgfVxufTtcblxuLy8gQ29udmVydCBJbnQzMkFycmF5IGRhdGEgdG8gb3JpZ2luYWwgaW50ZWdlciBkYXRhIGJ1ZmZlci5cbi8vIFN1cHBvcnRzIGNvbnZlcnNpb24gZnJvbSBpbnQzMiB0byBpbnQ2NCwgdWludDY0LCB1aW50MzIsIGludDggYW5kIHVpbnQ4LlxuZXhwb3J0IGNvbnN0IGNvbnZlcnRJbnQzMlRvRGF0YSA9IChkYXRhOiBVaW50OEFycmF5LCBkYXRhVHlwZTogTUxPcGVyYW5kRGF0YVR5cGUpOiBVaW50OEFycmF5ID0+IHtcbiAgaWYgKGRhdGFUeXBlID09PSAnaW50MzInKSB7XG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cblxuICAvLyBNYWtlIHN1cmUgdGhlIGRhdGEgbGVuZ3RoIGlzIGEgbXVsdGlwbGUgb2YgNCBieXRlcyAoSW50MzJBcnJheSkuXG4gIGlmIChkYXRhLmJ5dGVMZW5ndGggJSA0ICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIFVpbnQ4QXJyYXkgbGVuZ3RoIC0gbXVzdCBiZSBhIG11bHRpcGxlIG9mIDQgKGludDMyKS4nKTtcbiAgfVxuXG4gIC8vIENvbnZlcnQgVWludDhBcnJheSB0byBJbnQzMkFycmF5LlxuICBjb25zdCBudW1FbGVtZW50cyA9IGRhdGEuYnl0ZUxlbmd0aCAvIDQ7XG4gIGNvbnN0IGludDMyQXJyYXkgPSBuZXcgSW50MzJBcnJheShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBudW1FbGVtZW50cyk7XG5cbiAgc3dpdGNoIChkYXRhVHlwZSkge1xuICAgIGNhc2UgJ2ludDY0Jzoge1xuICAgICAgY29uc3QgYmlnSW50NjRBcnJheSA9IEJpZ0ludDY0QXJyYXkuZnJvbShpbnQzMkFycmF5LCBCaWdJbnQpO1xuICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGJpZ0ludDY0QXJyYXkuYnVmZmVyKTtcbiAgICB9XG4gICAgY2FzZSAndWludDY0Jzoge1xuICAgICAgaWYgKGludDMyQXJyYXkuc29tZSgodmFsdWUpID0+IHZhbHVlIDwgMCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IGNvbnZlcnQgaW50MzIgZGF0YSB0byB1aW42NCAtIG5lZ2F0aXZlIHZhbHVlIGZvdW5kLicpO1xuICAgICAgfVxuICAgICAgY29uc3QgYmlnVWludDY0QXJyYXkgPSBCaWdVaW50NjRBcnJheS5mcm9tKGludDMyQXJyYXksIEJpZ0ludCk7XG4gICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYmlnVWludDY0QXJyYXkuYnVmZmVyKTtcbiAgICB9XG4gICAgY2FzZSAnaW50OCc6IHtcbiAgICAgIGlmIChpbnQzMkFycmF5LnNvbWUoKHZhbHVlKSA9PiB2YWx1ZSA8IC0xMjggfHwgdmFsdWUgPiAxMjcpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBjb252ZXJ0IGludDMyIGRhdGEgdG8gaW50OCAtIHZhbHVlIG91dCBvZiByYW5nZS4nKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGludDhBcnJheSA9IEludDhBcnJheS5mcm9tKGludDMyQXJyYXksIE51bWJlcik7XG4gICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoaW50OEFycmF5LmJ1ZmZlcik7XG4gICAgfVxuICAgIGNhc2UgJ3VpbnQ4Jzoge1xuICAgICAgaWYgKGludDMyQXJyYXkuc29tZSgodmFsdWUpID0+IHZhbHVlIDwgMCB8fCB2YWx1ZSA+IDI1NSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IGNvbnZlcnQgaW50MzIgZGF0YSB0byB1aW50OCAtIHZhbHVlIG91dCBvZiByYW5nZS4nKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBVaW50OEFycmF5LmZyb20oaW50MzJBcnJheSwgTnVtYmVyKTtcbiAgICB9XG4gICAgY2FzZSAndWludDMyJzoge1xuICAgICAgaWYgKGludDMyQXJyYXkuc29tZSgodmFsdWUpID0+IHZhbHVlIDwgMCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IGNvbnZlcnQgaW50MzIgZGF0YSB0byB1aW50MzIgLSBuZWdhdGl2ZSB2YWx1ZSBmb3VuZC4nKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVpbnQzMkFycmF5ID0gVWludDMyQXJyYXkuZnJvbShpbnQzMkFycmF5LCBOdW1iZXIpO1xuICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KHVpbnQzMkFycmF5LmJ1ZmZlcik7XG4gICAgfVxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGRhdGEgY29udmVyc2lvbiBmcm9tICdpbnQzMicgdG8gJHtkYXRhVHlwZX1gKTtcbiAgfVxufTtcblxuZXhwb3J0IHR5cGUgVGVuc29ySWQgPSBudW1iZXI7XG5cbi8qKlxuICogTWFuYWdlcyBUZW5zb3JJZCB0byBNTFRlbnNvciBtYXBwaW5nLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvck1hbmFnZXIge1xuICAvKipcbiAgICogUmVzZXJ2ZSBhIG5ldyBUZW5zb3JJZC5cbiAgICovXG4gIHJlc2VydmVUZW5zb3JJZCgpOiBUZW5zb3JJZDtcbiAgLyoqXG4gICAqIFJlbGVhc2UgYSBUZW5zb3JJZC5cbiAgICovXG4gIHJlbGVhc2VUZW5zb3JJZCh0ZW5zb3JJZDogVGVuc29ySWQpOiB2b2lkO1xuICAvKipcbiAgICogRW5zdXJlIGEgTUxUZW5zb3IgaXMgY3JlYXRlZCBmb3IgdGhlIFRlbnNvcklkLlxuICAgKi9cbiAgZW5zdXJlVGVuc29yKFxuICAgIHNlc3Npb25JZDogbnVtYmVyLFxuICAgIHRlbnNvcklkOiBUZW5zb3JJZCxcbiAgICBkYXRhVHlwZTogTUxPcGVyYW5kRGF0YVR5cGUsXG4gICAgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGNvcHlPbGQ6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8TUxUZW5zb3I+O1xuICAvKipcbiAgICogVXBsb2FkIGRhdGEgdG8gYSBNTFRlbnNvci5cbiAgICovXG4gIHVwbG9hZCh0ZW5zb3JJZDogVGVuc29ySWQsIGRhdGE6IFVpbnQ4QXJyYXkpOiB2b2lkO1xuICAvKipcbiAgICogRG93bmxvYWQgZGF0YSBmcm9tIGEgTUxUZW5zb3IuXG4gICAqL1xuICBkb3dubG9hZCh0ZW5zb3JJZDogVGVuc29ySWQpOiBQcm9taXNlPEFycmF5QnVmZmVyPjtcbiAgZG93bmxvYWQodGVuc29ySWQ6IFRlbnNvcklkLCBkc3RUZW5zb3I6IEFycmF5QnVmZmVyVmlldyB8IEFycmF5QnVmZmVyKTogUHJvbWlzZTx1bmRlZmluZWQ+O1xuICAvKipcbiAgICogUmVsZWFzZSBhbGwgdGVuc29ycyBmb3IgYSBnaXZlbiBzZXNzaW9uLlxuICAgKi9cbiAgcmVsZWFzZVRlbnNvcnNGb3JTZXNzaW9uKHNlc3Npb246IG51bWJlcik6IHZvaWQ7XG4gIC8qKlxuICAgKiBSZWdpc3RlciBhbiBleHRlcm5hbGx5IGNyZWF0ZWQgTUxUZW5zb3Igd2l0aCBhIGdpdmVuIHNlc3Npb24gaWQgYW5kIHJldHVybiBhIFRlbnNvcklkLlxuICAgKi9cbiAgcmVnaXN0ZXJUZW5zb3Ioc2Vzc2lvbklkOiBudW1iZXIsIG1sVGVuc29yOiBNTFRlbnNvciwgZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlLCBzaGFwZTogbnVtYmVyW10pOiBUZW5zb3JJZDtcbn1cblxubGV0IHRlbnNvckd1aWQgPSAxO1xuY29uc3QgY3JlYXRlTmV3VGVuc29ySWQgPSAoKTogVGVuc29ySWQgPT4gdGVuc29yR3VpZCsrO1xuXG4vKipcbiAqIE1hcCBmcm9tIGRhdGEgdHlwZSB0byBmYWxsYmFjayBkYXRhIHR5cGUuXG4gKiBXaGVuIHRoZSBjb250ZXh0IGRvZXMgbm90IHN1cHBvcnQgdGhlIG9yaWdpbmFsIGRhdGEgdHlwZSwgdXNlIGZhbGxiYWNrIGRhdGEgdHlwZSBhcyB3b3JrYXJvdW5kLlxuICogTm90ZTogQ3VycmVudGx5LCB3ZSBvbmx5IHN1cHBvcnQgZmFsbGJhY2sgdG8gaW50MzIgZm9yIGNlcnRhaW4gaW50ZWdlciBkYXRhIHR5cGVzLlxuICovXG5jb25zdCB3ZWJubkRhdGFUeXBlVG9GYWxsYmFjayA9IG5ldyBNYXA8TUxPcGVyYW5kRGF0YVR5cGUsIE1MT3BlcmFuZERhdGFUeXBlPihbXG4gIFsnaW50OCcsICdpbnQzMiddLFxuICBbJ3VpbnQ4JywgJ2ludDMyJ10sXG4gIFsndWludDMyJywgJ2ludDMyJ10sXG4gIFsnaW50NjQnLCAnaW50MzInXSxcbl0pO1xuXG4vKipcbiAqIENhbGN1bGF0ZSB0aGUgYnl0ZSBsZW5ndGggb2YgYSB0ZW5zb3Igd2l0aCB0aGUgZ2l2ZW4gZGF0YSB0eXBlIGFuZCBzaGFwZS5cbiAqL1xuY29uc3QgY2FsY3VsYXRlQnl0ZUxlbmd0aCA9IChkYXRhVHlwZTogTUxPcGVyYW5kRGF0YVR5cGUsIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSk6IG51bWJlciA9PiB7XG4gIGNvbnN0IGRhdGFUeXBlU2l6ZSA9IHdlYm5uRGF0YVR5cGVUb1NpemUuZ2V0KGRhdGFUeXBlKTtcbiAgaWYgKCFkYXRhVHlwZVNpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFdlYk5OIGJhY2tlbmQgZG9lcyBub3Qgc3VwcG9ydCBkYXRhIHR5cGU6ICR7ZGF0YVR5cGV9YCk7XG4gIH1cbiAgcmV0dXJuIHNoYXBlLmxlbmd0aCA+IDAgPyBNYXRoLmNlaWwoKHNoYXBlLnJlZHVjZSgoYSwgYikgPT4gYSAqIGIpICogZGF0YVR5cGVTaXplKSAvIDgpIDogMDtcbn07XG5cbi8qKlxuICogVGVuc29yV3JhcHBlciB3cmFwcyBhbiBNTFRlbnNvciBhbmQgcHJvdmlkZXMgYSB3YXkgdG8gdHJhY2sgdGhlIGxhc3Qgc2Vzc2lvbiB0aGF0IHVzZWQgaXQuXG4gKi9cbmNsYXNzIFRlbnNvcldyYXBwZXIge1xuICAvLyBUaGUgaWQgb2YgdGhlIGxhc3Qgc2Vzc2lvbiB0aGF0IHVzZWQgdGhpcyB0ZW5zb3IuXG4gIHB1YmxpYyBzZXNzaW9uSWQ6IG51bWJlcjtcbiAgLy8gVGhpcyBmbGFnIGlzIHVzZWQgdG8gaW5kaWNhdGUgd2hldGhlciB0aGUgZGF0YSBoYXMgYmVlbiBjb252ZXJ0ZWQgdG8gZmFsbGJhY2sgZGF0YSB0eXBlLlxuICBwdWJsaWMgaXNEYXRhQ29udmVydGVkID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSBtbENvbnRleHQ6IE1MQ29udGV4dDtcbiAgcHJpdmF0ZSBtbFRlbnNvcjogTUxUZW5zb3I7XG4gIHByaXZhdGUgZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlO1xuICAvLyBGYWxsYmFjayBkYXRhIHR5cGUgdG8gdXNlIHdoZW4gdGhlIGNvbnRleHQgZG9lcyBub3Qgc3VwcG9ydCB0aGUgb3JpZ2luYWwgZGF0YSB0eXBlLlxuICBwcml2YXRlIGZhbGxiYWNrRGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHRlbnNvclNoYXBlOiByZWFkb25seSBudW1iZXJbXTtcblxuICBjb25zdHJ1Y3RvcihkZXNjcmlwdG9yOiB7XG4gICAgc2Vzc2lvbklkOiBudW1iZXI7XG4gICAgY29udGV4dDogTUxDb250ZXh0O1xuICAgIHRlbnNvcjogTUxUZW5zb3I7XG4gICAgZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlO1xuICAgIHNoYXBlOiByZWFkb25seSBudW1iZXJbXTtcbiAgICBmYWxsYmFja0RhdGFUeXBlPzogTUxPcGVyYW5kRGF0YVR5cGU7XG4gIH0pIHtcbiAgICBjb25zdCB7IHNlc3Npb25JZCwgY29udGV4dCwgdGVuc29yLCBkYXRhVHlwZSwgc2hhcGUsIGZhbGxiYWNrRGF0YVR5cGUgfSA9IGRlc2NyaXB0b3I7XG4gICAgdGhpcy5zZXNzaW9uSWQgPSBzZXNzaW9uSWQ7XG4gICAgdGhpcy5tbENvbnRleHQgPSBjb250ZXh0O1xuICAgIHRoaXMubWxUZW5zb3IgPSB0ZW5zb3I7XG4gICAgdGhpcy5kYXRhVHlwZSA9IGRhdGFUeXBlO1xuICAgIHRoaXMudGVuc29yU2hhcGUgPSBzaGFwZTtcbiAgICB0aGlzLmZhbGxiYWNrRGF0YVR5cGUgPSBmYWxsYmFja0RhdGFUeXBlO1xuICB9XG5cbiAgcHVibGljIGdldCB0ZW5zb3IoKTogTUxUZW5zb3Ige1xuICAgIHJldHVybiB0aGlzLm1sVGVuc29yO1xuICB9XG5cbiAgcHVibGljIGdldCB0eXBlKCk6IE1MT3BlcmFuZERhdGFUeXBlIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhVHlwZTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgZmFsbGJhY2tUeXBlKCk6IE1MT3BlcmFuZERhdGFUeXBlIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5mYWxsYmFja0RhdGFUeXBlO1xuICB9XG5cbiAgcHVibGljIGdldCBzaGFwZSgpOiByZWFkb25seSBudW1iZXJbXSB7XG4gICAgcmV0dXJuIHRoaXMudGVuc29yU2hhcGU7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGJ5dGVMZW5ndGgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gY2FsY3VsYXRlQnl0ZUxlbmd0aCh0aGlzLmRhdGFUeXBlLCB0aGlzLnRlbnNvclNoYXBlKTtcbiAgfVxuXG4gIHB1YmxpYyBkZXN0cm95KCk6IHZvaWQge1xuICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+ICdbV2ViTk5dIFRlbnNvcldyYXBwZXIuZGVzdHJveScpO1xuICAgIHRoaXMubWxUZW5zb3IuZGVzdHJveSgpO1xuICB9XG5cbiAgcHVibGljIHdyaXRlKGRhdGE6IFVpbnQ4QXJyYXkpOiB2b2lkIHtcbiAgICB0aGlzLm1sQ29udGV4dC53cml0ZVRlbnNvcih0aGlzLm1sVGVuc29yLCBkYXRhKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyByZWFkKCk6IFByb21pc2U8QXJyYXlCdWZmZXI+O1xuICBwdWJsaWMgYXN5bmMgcmVhZChkc3RCdWZmZXI/OiBBcnJheUJ1ZmZlclZpZXcgfCBBcnJheUJ1ZmZlcik6IFByb21pc2U8QXJyYXlCdWZmZXIgfCB1bmRlZmluZWQ+O1xuICBwdWJsaWMgYXN5bmMgcmVhZChkc3RCdWZmZXI/OiBBcnJheUJ1ZmZlclZpZXcgfCBBcnJheUJ1ZmZlcik6IFByb21pc2U8QXJyYXlCdWZmZXIgfCB1bmRlZmluZWQ+IHtcbiAgICBpZiAodGhpcy5mYWxsYmFja0RhdGFUeXBlKSB7XG4gICAgICAvLyBUaGlzIHRlbnNvciBoYXMgYmVlbiBmYWxsYmFjayB0byBpbnQzMiBhcyB3b3JrYXJvdW5kLCB3ZSBuZWVkIHRvIHJlYWQgaXQgYXMgaXRzIG9yaWdpbmFsIGludGVnZXIgZGF0YSB0eXBlLlxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMubWxDb250ZXh0LnJlYWRUZW5zb3IodGhpcy5tbFRlbnNvcik7XG4gICAgICBjb25zdCBvcmlnaW5hbERhdGEgPSBjb252ZXJ0SW50MzJUb0RhdGEobmV3IFVpbnQ4QXJyYXkoZGF0YSksIHRoaXMuZGF0YVR5cGUpO1xuXG4gICAgICBpZiAoZHN0QnVmZmVyKSB7XG4gICAgICAgIGNvbnN0IHRhcmdldEJ1ZmZlciA9XG4gICAgICAgICAgZHN0QnVmZmVyIGluc3RhbmNlb2YgQXJyYXlCdWZmZXJcbiAgICAgICAgICAgID8gbmV3IFVpbnQ4QXJyYXkoZHN0QnVmZmVyKVxuICAgICAgICAgICAgOiBuZXcgVWludDhBcnJheShkc3RCdWZmZXIuYnVmZmVyLCBkc3RCdWZmZXIuYnl0ZU9mZnNldCwgZHN0QnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB0YXJnZXRCdWZmZXIuc2V0KG9yaWdpbmFsRGF0YSk7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gb3JpZ2luYWxEYXRhLmJ1ZmZlcjtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGRzdEJ1ZmZlciA/IHRoaXMubWxDb250ZXh0LnJlYWRUZW5zb3IodGhpcy5tbFRlbnNvciwgZHN0QnVmZmVyKSA6IHRoaXMubWxDb250ZXh0LnJlYWRUZW5zb3IodGhpcy5tbFRlbnNvcik7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGNhblJldXNlVGVuc29yKGNvbnRleHQ6IE1MQ29udGV4dCwgZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlLCBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5tbENvbnRleHQgPT09IGNvbnRleHQgJiZcbiAgICAgIHRoaXMuZGF0YVR5cGUgPT09IGRhdGFUeXBlICYmXG4gICAgICB0aGlzLnRlbnNvclNoYXBlLmxlbmd0aCA9PT0gc2hhcGUubGVuZ3RoICYmXG4gICAgICB0aGlzLnRlbnNvclNoYXBlLmV2ZXJ5KCh2LCBpKSA9PiB2ID09PSBzaGFwZVtpXSlcbiAgICApO1xuICB9XG5cbiAgcHVibGljIHNldElzRGF0YUNvbnZlcnRlZChpc0NvbnZlcnRlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuaXNEYXRhQ29udmVydGVkID0gaXNDb252ZXJ0ZWQ7XG4gIH1cbn1cblxuLyoqXG4gKiBUZW5zb3JUcmFja2VyIHRyYWNrcyB0aGUgTUxUZW5zb3IgYW5kIHBlbmRpbmcgdXBsb2FkIGRhdGEuXG4gKlxuICogV2UgbmVlZCB0byB0cmFjayB0aGUgTUxUZW5zb3IgYW5kIHBlbmRpbmcgdXBsb2FkIGRhdGEgYmVjYXVzZSB3ZSBkZWxheSB0aGUgY3JlYXRpb24gb2YgTUxUZW5zb3IgdW50aWxcbiAqIHdlIGtub3cgdGhlIGRhdGEgdHlwZSBhbmQgc2hhcGUuIFRoaXMgaXMgYmVjYXVzZSBXZWJOTiBvbmx5IHN1cHBvcnQgY3JlYXRpbmcgTUxUZW5zb3JzIHdpdGggZGF0YVR5cGVzIGFuZCBzaGFwZS5cbiAqL1xuY2xhc3MgVGVuc29ySWRUcmFja2VyIHtcbiAgcHJpdmF0ZSBhY3RpdmVVcGxvYWQ/OiBVaW50OEFycmF5O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgdGVuc29yTWFuYWdlcjogVGVuc29yTWFuYWdlckltcGwsXG4gICAgcHJpdmF0ZSB3cmFwcGVyPzogVGVuc29yV3JhcHBlcixcbiAgKSB7fVxuXG4gIHB1YmxpYyBnZXQgdGVuc29yV3JhcHBlcigpOiBUZW5zb3JXcmFwcGVyIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy53cmFwcGVyO1xuICB9XG5cbiAgcHVibGljIHJlbGVhc2VUZW5zb3IoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMudGVuc29yV3JhcHBlcikge1xuICAgICAgdGhpcy50ZW5zb3JNYW5hZ2VyLnJlbGVhc2VUZW5zb3IodGhpcy50ZW5zb3JXcmFwcGVyKTtcbiAgICAgIHRoaXMud3JhcHBlciA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZW5zdXJlVGVuc29yKFxuICAgIHNlc3Npb25JZDogbnVtYmVyLFxuICAgIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZSxcbiAgICBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgY29weU9sZDogYm9vbGVhbixcbiAgKTogUHJvbWlzZTxNTFRlbnNvcj4ge1xuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLnRlbnNvck1hbmFnZXIuZ2V0TUxDb250ZXh0KHNlc3Npb25JZCk7XG4gICAgbGV0IGZhbGxiYWNrRGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlIHwgdW5kZWZpbmVkO1xuICAgIC8vIENoZWNrIGlmIHRoZSBjb250ZXh0IHN1cHBvcnRzIHRoZSBkYXRhIHR5cGUuIElmIG5vdCwgdHJ5IHRvIHVzZSB0aGUgZmFsbGJhY2sgZGF0YSB0eXBlLlxuICAgIGlmICghY29udGV4dC5vcFN1cHBvcnRMaW1pdHMoKS5pbnB1dC5kYXRhVHlwZXMuaW5jbHVkZXMoZGF0YVR5cGUpKSB7XG4gICAgICBmYWxsYmFja0RhdGFUeXBlID0gd2Vibm5EYXRhVHlwZVRvRmFsbGJhY2suZ2V0KGRhdGFUeXBlKTtcbiAgICAgIGlmICghZmFsbGJhY2tEYXRhVHlwZSB8fCAhY29udGV4dC5vcFN1cHBvcnRMaW1pdHMoKS5pbnB1dC5kYXRhVHlwZXMuaW5jbHVkZXMoZmFsbGJhY2tEYXRhVHlwZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBXZWJOTiBiYWNrZW5kIGRvZXMgbm90IHN1cHBvcnQgZGF0YSB0eXBlOiAke2RhdGFUeXBlfWApO1xuICAgICAgfVxuICAgICAgTE9HX0RFQlVHKFxuICAgICAgICAndmVyYm9zZScsXG4gICAgICAgICgpID0+IGBbV2ViTk5dIFRlbnNvcklkVHJhY2tlci5lbnN1cmVUZW5zb3I6IGZhbGxiYWNrIGRhdGFUeXBlIGZyb20gJHtkYXRhVHlwZX0gdG8gJHtmYWxsYmFja0RhdGFUeXBlfWAsXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLndyYXBwZXIpIHtcbiAgICAgIGlmICh0aGlzLndyYXBwZXIuY2FuUmV1c2VUZW5zb3IoY29udGV4dCwgZGF0YVR5cGUsIHNoYXBlKSkge1xuICAgICAgICByZXR1cm4gdGhpcy53cmFwcGVyLnRlbnNvcjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChjb3B5T2xkKSB7XG4gICAgICAgICAgaWYgKHRoaXMud3JhcHBlci5ieXRlTGVuZ3RoICE9PSBjYWxjdWxhdGVCeXRlTGVuZ3RoKGRhdGFUeXBlLCBzaGFwZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGNvcHkgZGF0YSB0byB0ZW5zb3Igd2l0aCBkaWZmZXJlbnQgc2l6ZS4nKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5hY3RpdmVVcGxvYWQgPSBuZXcgVWludDhBcnJheShhd2FpdCB0aGlzLndyYXBwZXIucmVhZCgpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRlbnNvck1hbmFnZXIucmVsZWFzZVRlbnNvcih0aGlzLndyYXBwZXIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgY29uc3QgdXNhZ2UgPSB0eXBlb2YgTUxUZW5zb3JVc2FnZSA9PSAndW5kZWZpbmVkJyA/IHVuZGVmaW5lZCA6IE1MVGVuc29yVXNhZ2UuUkVBRCB8IE1MVGVuc29yVXNhZ2UuV1JJVEU7XG4gICAgdGhpcy53cmFwcGVyID0gYXdhaXQgdGhpcy50ZW5zb3JNYW5hZ2VyLmdldENhY2hlZFRlbnNvcihcbiAgICAgIHNlc3Npb25JZCxcbiAgICAgIGRhdGFUeXBlLFxuICAgICAgc2hhcGUsXG4gICAgICB1c2FnZSxcbiAgICAgIHRydWUsXG4gICAgICB0cnVlLFxuICAgICAgZmFsbGJhY2tEYXRhVHlwZSxcbiAgICApO1xuXG4gICAgaWYgKGNvcHlPbGQgJiYgdGhpcy5hY3RpdmVVcGxvYWQpIHtcbiAgICAgIC8vIFdlIGRvbid0IG5lZWQgdG8gY29udmVydCB0aGUgb3JpZ2luYWwgaW50ZWdlciBkYXRhIHRvIGludDMyLFxuICAgICAgLy8gYmVjYXVzZSBpdCBoYXMgYmVlbiBjb252ZXJ0ZWQgd2hlbiBpdCB3YXMgdXBsb2FkZWQuXG4gICAgICB0aGlzLndyYXBwZXIud3JpdGUodGhpcy5hY3RpdmVVcGxvYWQpO1xuICAgICAgdGhpcy5hY3RpdmVVcGxvYWQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMud3JhcHBlci50ZW5zb3I7XG4gIH1cblxuICBwdWJsaWMgdXBsb2FkKGRhdGE6IFVpbnQ4QXJyYXkpOiB2b2lkIHtcbiAgICBsZXQgbmV3RGF0YSA9IGRhdGE7XG4gICAgaWYgKHRoaXMud3JhcHBlcikge1xuICAgICAgaWYgKHRoaXMud3JhcHBlci5mYWxsYmFja1R5cGUpIHtcbiAgICAgICAgaWYgKHRoaXMud3JhcHBlci5mYWxsYmFja1R5cGUgPT09ICdpbnQzMicpIHtcbiAgICAgICAgICAvLyBDb252ZXJ0IG9yaWdpbmFsIGludGVnZXIgZGF0YSB0byBpbnQzMi5cbiAgICAgICAgICBuZXdEYXRhID0gY29udmVydERhdGFUb0ludDMyKGRhdGEsIHRoaXMud3JhcHBlci50eXBlKTtcbiAgICAgICAgICB0aGlzLndyYXBwZXIuc2V0SXNEYXRhQ29udmVydGVkKHRydWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgZmFsbGJhY2sgZGF0YSB0eXBlOiAke3RoaXMud3JhcHBlci5mYWxsYmFja1R5cGV9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgdGhlIGRhdGEgc2l6ZSBtYXRjaGVzIHRoZSB0ZW5zb3Igc2l6ZS5cbiAgICAgIGlmIChkYXRhLmJ5dGVMZW5ndGggPT09IHRoaXMud3JhcHBlci5ieXRlTGVuZ3RoKSB7XG4gICAgICAgIC8vIFdyaXRlIHRoZSBuZXdEYXRhIHRvIHRoZSB0ZW5zb3IuXG4gICAgICAgIHRoaXMud3JhcHBlci53cml0ZShuZXdEYXRhKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gJ0RhdGEgc2l6ZSBkb2VzIG5vdCBtYXRjaCB0ZW5zb3Igc2l6ZS4gUmVsZWFzaW5nIHRlbnNvci4nKTtcbiAgICAgICAgdGhpcy5yZWxlYXNlVGVuc29yKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYWN0aXZlVXBsb2FkKSB7XG4gICAgICB0aGlzLmFjdGl2ZVVwbG9hZC5zZXQobmV3RGF0YSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYWN0aXZlVXBsb2FkID0gbmV3IFVpbnQ4QXJyYXkobmV3RGF0YSk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIGRvd25sb2FkKGRzdEJ1ZmZlcj86IEFycmF5QnVmZmVyVmlldyB8IEFycmF5QnVmZmVyKTogUHJvbWlzZTxBcnJheUJ1ZmZlciB8IHVuZGVmaW5lZD4ge1xuICAgIGlmICh0aGlzLmFjdGl2ZVVwbG9hZCkge1xuICAgICAgLy8gSWYgdGhpcy5hY3RpdmVVcGxvYWQgaGFzIGJlZW4gY29udmVydGVkIHRvIGludDMyLCB3ZSBuZWVkIHRvIGNvbnZlcnQgaXQgYmFjayB0byBvcmlnaW5hbCBpbnRlZ2VyIGRhdGEgdHlwZS5cbiAgICAgIGNvbnN0IGRzdERhdGEgPSB0aGlzLndyYXBwZXI/LmlzRGF0YUNvbnZlcnRlZFxuICAgICAgICA/IGNvbnZlcnRJbnQzMlRvRGF0YSh0aGlzLmFjdGl2ZVVwbG9hZCwgdGhpcy53cmFwcGVyPy50eXBlKVxuICAgICAgICA6IHRoaXMuYWN0aXZlVXBsb2FkO1xuXG4gICAgICBpZiAoZHN0QnVmZmVyKSB7XG4gICAgICAgIGlmIChkc3RCdWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgICAgICAgIG5ldyBVaW50OEFycmF5KGRzdEJ1ZmZlcikuc2V0KGRzdERhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5ldyBVaW50OEFycmF5KGRzdEJ1ZmZlci5idWZmZXIsIGRzdEJ1ZmZlci5ieXRlT2Zmc2V0LCBkc3RCdWZmZXIuYnl0ZUxlbmd0aCkuc2V0KGRzdERhdGEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBkc3REYXRhLmJ1ZmZlcjtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCF0aGlzLndyYXBwZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGVuc29yIGhhcyBub3QgYmVlbiBjcmVhdGVkLicpO1xuICAgIH1cblxuICAgIGlmICghZHN0QnVmZmVyKSB7XG4gICAgICByZXR1cm4gdGhpcy53cmFwcGVyLnJlYWQoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMud3JhcHBlci5yZWFkKGRzdEJ1ZmZlcik7XG4gIH1cbn1cblxuY2xhc3MgVGVuc29yTWFuYWdlckltcGwgaW1wbGVtZW50cyBUZW5zb3JNYW5hZ2VyIHtcbiAgcHJpdmF0ZSB0ZW5zb3JUcmFja2Vyc0J5SWQ6IE1hcDxUZW5zb3JJZCwgVGVuc29ySWRUcmFja2VyPiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBmcmVlVGVuc29yczogVGVuc29yV3JhcHBlcltdID0gW107XG4gIHByaXZhdGUgZXh0ZXJuYWxUZW5zb3JzOiBTZXQ8VGVuc29yV3JhcHBlcj4gPSBuZXcgU2V0KCk7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBiYWNrZW5kOiBXZWJOTkJhY2tlbmQpIHt9XG5cbiAgcHVibGljIGdldE1MQ29udGV4dChzZXNzaW9uSWQ6IG51bWJlcik6IE1MQ29udGV4dCB7XG4gICAgY29uc3QgY29udGV4dCA9IHRoaXMuYmFja2VuZC5nZXRNTENvbnRleHQoc2Vzc2lvbklkKTtcbiAgICBpZiAoIWNvbnRleHQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTUxDb250ZXh0IG5vdCBmb3VuZCBmb3Igc2Vzc2lvbi4nKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbnRleHQ7XG4gIH1cblxuICBwdWJsaWMgcmVzZXJ2ZVRlbnNvcklkKCk6IFRlbnNvcklkIHtcbiAgICBjb25zdCB0ZW5zb3JJZCA9IGNyZWF0ZU5ld1RlbnNvcklkKCk7XG4gICAgdGhpcy50ZW5zb3JUcmFja2Vyc0J5SWQuc2V0KHRlbnNvcklkLCBuZXcgVGVuc29ySWRUcmFja2VyKHRoaXMpKTtcbiAgICByZXR1cm4gdGVuc29ySWQ7XG4gIH1cblxuICBwdWJsaWMgcmVsZWFzZVRlbnNvcklkKHRlbnNvcklkOiBUZW5zb3JJZCk6IHZvaWQge1xuICAgIGNvbnN0IHRlbnNvclRyYWNrZXIgPSB0aGlzLnRlbnNvclRyYWNrZXJzQnlJZC5nZXQodGVuc29ySWQpO1xuICAgIGlmICghdGVuc29yVHJhY2tlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnRlbnNvclRyYWNrZXJzQnlJZC5kZWxldGUodGVuc29ySWQpO1xuICAgIGlmICh0ZW5zb3JUcmFja2VyLnRlbnNvcldyYXBwZXIpIHtcbiAgICAgIHRoaXMucmVsZWFzZVRlbnNvcih0ZW5zb3JUcmFja2VyLnRlbnNvcldyYXBwZXIpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBlbnN1cmVUZW5zb3IoXG4gICAgc2Vzc2lvbklkOiBudW1iZXIsXG4gICAgdGVuc29ySWQ6IFRlbnNvcklkLFxuICAgIGRhdGFUeXBlOiBNTE9wZXJhbmREYXRhVHlwZSxcbiAgICBzaGFwZTogbnVtYmVyW10sXG4gICAgY29weU9sZDogYm9vbGVhbixcbiAgKTogUHJvbWlzZTxNTFRlbnNvcj4ge1xuICAgIExPR19ERUJVRyhcbiAgICAgICd2ZXJib3NlJyxcbiAgICAgICgpID0+XG4gICAgICAgIGBbV2ViTk5dIFRlbnNvck1hbmFnZXIuZW5zdXJlVGVuc29yIHt0ZW5zb3JJZDogJHt0ZW5zb3JJZH0sIGRhdGFUeXBlOiAke1xuICAgICAgICAgIGRhdGFUeXBlXG4gICAgICAgIH0sIHNoYXBlOiAke3NoYXBlfSwgY29weU9sZDogJHtjb3B5T2xkfX1gLFxuICAgICk7XG4gICAgY29uc3QgdGVuc29yID0gdGhpcy50ZW5zb3JUcmFja2Vyc0J5SWQuZ2V0KHRlbnNvcklkKTtcbiAgICBpZiAoIXRlbnNvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUZW5zb3Igbm90IGZvdW5kLicpO1xuICAgIH1cbiAgICByZXR1cm4gdGVuc29yLmVuc3VyZVRlbnNvcihzZXNzaW9uSWQsIGRhdGFUeXBlLCBzaGFwZSwgY29weU9sZCk7XG4gIH1cblxuICBwdWJsaWMgdXBsb2FkKHRlbnNvcklkOiBUZW5zb3JJZCwgZGF0YTogVWludDhBcnJheSk6IHZvaWQge1xuICAgIGNvbnN0IHRlbnNvciA9IHRoaXMudGVuc29yVHJhY2tlcnNCeUlkLmdldCh0ZW5zb3JJZCk7XG4gICAgaWYgKCF0ZW5zb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGVuc29yIG5vdCBmb3VuZC4nKTtcbiAgICB9XG4gICAgdGVuc29yLnVwbG9hZChkYXRhKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBkb3dubG9hZCh0ZW5zb3JJZDogVGVuc29ySWQpOiBQcm9taXNlPEFycmF5QnVmZmVyPjtcbiAgcHVibGljIGFzeW5jIGRvd25sb2FkKHRlbnNvcklkOiBUZW5zb3JJZCwgZHN0QnVmZmVyOiBBcnJheUJ1ZmZlclZpZXcgfCBBcnJheUJ1ZmZlcik6IFByb21pc2U8dW5kZWZpbmVkPjtcbiAgYXN5bmMgZG93bmxvYWQodGVuc29ySWQ6IFRlbnNvcklkLCBkc3RCdWZmZXI/OiBBcnJheUJ1ZmZlclZpZXcgfCBBcnJheUJ1ZmZlcik6IFByb21pc2U8QXJyYXlCdWZmZXIgfCB1bmRlZmluZWQ+IHtcbiAgICBMT0dfREVCVUcoXG4gICAgICAndmVyYm9zZScsXG4gICAgICAoKSA9PiBgW1dlYk5OXSBUZW5zb3JNYW5hZ2VyLmRvd25sb2FkIHt0ZW5zb3JJZDogJHt0ZW5zb3JJZH0sIGRzdEJ1ZmZlcjogJHtkc3RCdWZmZXI/LmJ5dGVMZW5ndGh9fWAsXG4gICAgKTtcbiAgICBjb25zdCB0ZW5zb3JUcmFja2VyID0gdGhpcy50ZW5zb3JUcmFja2Vyc0J5SWQuZ2V0KHRlbnNvcklkKTtcbiAgICBpZiAoIXRlbnNvclRyYWNrZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGVuc29yIG5vdCBmb3VuZC4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRlbnNvclRyYWNrZXIuZG93bmxvYWQoZHN0QnVmZmVyKTtcbiAgfVxuXG4gIHB1YmxpYyByZWxlYXNlVGVuc29yc0ZvclNlc3Npb24oc2Vzc2lvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IHRlbnNvciBvZiB0aGlzLmZyZWVUZW5zb3JzKSB7XG4gICAgICBpZiAodGVuc29yLnNlc3Npb25JZCA9PT0gc2Vzc2lvbklkKSB7XG4gICAgICAgIHRlbnNvci5kZXN0cm95KCk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuZnJlZVRlbnNvcnMgPSB0aGlzLmZyZWVUZW5zb3JzLmZpbHRlcigodGVuc29yKSA9PiB0ZW5zb3Iuc2Vzc2lvbklkICE9PSBzZXNzaW9uSWQpO1xuICB9XG5cbiAgcHVibGljIHJlZ2lzdGVyVGVuc29yKFxuICAgIHNlc3Npb25JZDogbnVtYmVyLFxuICAgIG1sVGVuc29yOiBNTFRlbnNvcixcbiAgICBkYXRhVHlwZTogTUxPcGVyYW5kRGF0YVR5cGUsXG4gICAgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICApOiBUZW5zb3JJZCB7XG4gICAgY29uc3QgY29udGV4dCA9IHRoaXMuZ2V0TUxDb250ZXh0KHNlc3Npb25JZCk7XG4gICAgY29uc3QgdGVuc29ySWQgPSBjcmVhdGVOZXdUZW5zb3JJZCgpO1xuICAgIC8vIERlZmF1bHRpbmcgdG8gUkVBRCB8IFdSSVRFIGlmIHVzYWdlIGlzIG5vdCBwcm92aWRlZC5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgIGNvbnN0IHdyYXBwZXIgPSBuZXcgVGVuc29yV3JhcHBlcih7XG4gICAgICBzZXNzaW9uSWQsXG4gICAgICBjb250ZXh0LFxuICAgICAgdGVuc29yOiBtbFRlbnNvcixcbiAgICAgIGRhdGFUeXBlLFxuICAgICAgc2hhcGUsXG4gICAgfSk7XG4gICAgdGhpcy50ZW5zb3JUcmFja2Vyc0J5SWQuc2V0KHRlbnNvcklkLCBuZXcgVGVuc29ySWRUcmFja2VyKHRoaXMsIHdyYXBwZXIpKTtcbiAgICB0aGlzLmV4dGVybmFsVGVuc29ycy5hZGQod3JhcHBlcik7XG4gICAgcmV0dXJuIHRlbnNvcklkO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBvciBjcmVhdGUgYW4gTUxUZW5zb3Igd2l0aCB0aGUgZ2l2ZW4gZGF0YSB0eXBlIGFuZCBzaGFwZS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBnZXRDYWNoZWRUZW5zb3IoXG4gICAgc2Vzc2lvbklkOiBudW1iZXIsXG4gICAgZGF0YVR5cGU6IE1MT3BlcmFuZERhdGFUeXBlLFxuICAgIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgICB1c2FnZTogTUxUZW5zb3JVc2FnZUZsYWdzIHwgdW5kZWZpbmVkLFxuICAgIHdyaXRhYmxlOiBib29sZWFuLFxuICAgIHJlYWRhYmxlOiBib29sZWFuLFxuICAgIGZhbGxiYWNrRGF0YVR5cGU/OiBNTE9wZXJhbmREYXRhVHlwZSxcbiAgKTogUHJvbWlzZTxUZW5zb3JXcmFwcGVyPiB7XG4gICAgY29uc3QgY29udGV4dCA9IHRoaXMuZ2V0TUxDb250ZXh0KHNlc3Npb25JZCk7XG4gICAgZm9yIChjb25zdCBbaW5kZXgsIHRlbnNvcl0gb2YgdGhpcy5mcmVlVGVuc29ycy5lbnRyaWVzKCkpIHtcbiAgICAgIGlmICh0ZW5zb3IuY2FuUmV1c2VUZW5zb3IoY29udGV4dCwgZGF0YVR5cGUsIHNoYXBlKSkge1xuICAgICAgICBMT0dfREVCVUcoXG4gICAgICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgICAgICgpID0+XG4gICAgICAgICAgICBgW1dlYk5OXSBSZXVzaW5nIHRlbnNvciB7ZGF0YVR5cGU6ICR7ZGF0YVR5cGV9LCAke1xuICAgICAgICAgICAgICBmYWxsYmFja0RhdGFUeXBlID8gYGZhbGxiYWNrRGF0YVR5cGU6ICR7ZmFsbGJhY2tEYXRhVHlwZX0sYCA6ICcnXG4gICAgICAgICAgICB9IHNoYXBlOiAke3NoYXBlfWAsXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IHdyYXBwZXIgPSB0aGlzLmZyZWVUZW5zb3JzLnNwbGljZShpbmRleCwgMSlbMF07XG4gICAgICAgIHdyYXBwZXIuc2Vzc2lvbklkID0gc2Vzc2lvbklkO1xuICAgICAgICByZXR1cm4gd3JhcHBlcjtcbiAgICAgIH1cbiAgICB9XG4gICAgTE9HX0RFQlVHKFxuICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgKCkgPT5cbiAgICAgICAgYFtXZWJOTl0gTUxDb250ZXh0LmNyZWF0ZVRlbnNvciB7ZGF0YVR5cGU6ICR7ZGF0YVR5cGV9LCAke1xuICAgICAgICAgIGZhbGxiYWNrRGF0YVR5cGUgPyBgZmFsbGJhY2tEYXRhVHlwZTogJHtmYWxsYmFja0RhdGFUeXBlfSxgIDogJydcbiAgICAgICAgfSBzaGFwZTogJHtzaGFwZX19YCxcbiAgICApO1xuICAgIGNvbnN0IHRlbnNvciA9IGF3YWl0IGNvbnRleHQuY3JlYXRlVGVuc29yKHtcbiAgICAgIGRhdGFUeXBlOiBmYWxsYmFja0RhdGFUeXBlID8/IGRhdGFUeXBlLCAvLyBJZiBmYWxsYmFjayBkYXRhIHR5cGUgaXMgcHJvdmlkZWQsIHVzZSBpdC5cbiAgICAgIHNoYXBlLFxuICAgICAgZGltZW5zaW9uczogc2hhcGUsXG4gICAgICB1c2FnZSxcbiAgICAgIHdyaXRhYmxlLFxuICAgICAgcmVhZGFibGUsXG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBUZW5zb3JXcmFwcGVyKHsgc2Vzc2lvbklkLCBjb250ZXh0LCB0ZW5zb3IsIGRhdGFUeXBlLCBzaGFwZSwgZmFsbGJhY2tEYXRhVHlwZSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWxlYXNlIHRlbnNvciBmb3IgcmV1c2UgdW5sZXNzIGV4dGVybmFsLlxuICAgKi9cbiAgcHVibGljIHJlbGVhc2VUZW5zb3IodGVuc29yV3JhcHBlcjogVGVuc29yV3JhcHBlcikge1xuICAgIGlmICh0aGlzLmV4dGVybmFsVGVuc29ycy5oYXModGVuc29yV3JhcHBlcikpIHtcbiAgICAgIHRoaXMuZXh0ZXJuYWxUZW5zb3JzLmRlbGV0ZSh0ZW5zb3JXcmFwcGVyKTtcbiAgICB9XG4gICAgdGhpcy5mcmVlVGVuc29ycy5wdXNoKHRlbnNvcldyYXBwZXIpO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVUZW5zb3JNYW5hZ2VyID0gKC4uLmFyZ3M6IENvbnN0cnVjdG9yUGFyYW1ldGVyczx0eXBlb2YgVGVuc29yTWFuYWdlckltcGw+KTogVGVuc29yTWFuYWdlciA9PlxuICBuZXcgVGVuc29yTWFuYWdlckltcGwoLi4uYXJncyk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbi8vIFdlYk5OIEFQSSBjdXJyZW50bHkgZG9lcyBub3QgaGF2ZSBhIFR5cGVTY3JpcHQgZGVmaW5pdGlvbiBmaWxlLiBUaGlzIGZpbGUgaXMgYSB3b3JrYXJvdW5kIHdpdGggdHlwZXMgZ2VuZXJhdGVkIGZyb21cbi8vIFdlYk5OIEFQSSBzcGVjaWZpY2F0aW9uLlxuLy8gaHR0cHM6Ly9naXRodWIuY29tL3dlYm1hY2hpbmVsZWFybmluZy93ZWJubi9pc3N1ZXMvNjc3XG4vLy8gPHJlZmVyZW5jZSBwYXRoPVwid2Vibm4vd2Vibm4uZC50c1wiIC8+XG5cbmltcG9ydCB7IEVudiwgVGVuc29yIH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHsgRGF0YVR5cGUsIHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtIH0gZnJvbSAnLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgZ2V0SW5zdGFuY2UgfSBmcm9tICcuLi93YXNtLWZhY3RvcnknO1xuXG5pbXBvcnQgeyBjcmVhdGVWaWV3IH0gZnJvbSAnLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBUZW5zb3JJZCwgY3JlYXRlVGVuc29yTWFuYWdlciwgY29udmVydERhdGFUb0ludDMyIH0gZnJvbSAnLi93ZWJubi90ZW5zb3ItbWFuYWdlcic7XG5pbXBvcnQgeyBjb25maWd1cmVMb2dnZXIsIExPR19ERUJVRyB9IGZyb20gJy4vbG9nJztcblxuLypcbiAqIFRlbnNvclByb3RvOjpkYXRhX3R5cGUgdG8gV2ViTk4gT3BlcmFuZFR5cGUgbWFwcGluZy5cbiAqL1xuY29uc3Qgb25ueERhdGFUeXBlVG9XZWJubkRhdGFUeXBlID0gbmV3IE1hcDxEYXRhVHlwZSwgTUxPcGVyYW5kRGF0YVR5cGU+KFtcbiAgW0RhdGFUeXBlLmZsb2F0LCAnZmxvYXQzMiddLFxuICBbRGF0YVR5cGUuZmxvYXQxNiwgJ2Zsb2F0MTYnXSxcbiAgW0RhdGFUeXBlLmludDMyLCAnaW50MzInXSxcbiAgW0RhdGFUeXBlLnVpbnQzMiwgJ3VpbnQzMiddLFxuICBbRGF0YVR5cGUuaW50NjQsICdpbnQ2NCddLFxuICBbRGF0YVR5cGUudWludDY0LCAndWludDY0J10sXG4gIFtEYXRhVHlwZS5pbnQ0LCAnaW50NCddLFxuICBbRGF0YVR5cGUudWludDQsICd1aW50NCddLFxuICBbRGF0YVR5cGUuaW50OCwgJ2ludDgnXSxcbiAgW0RhdGFUeXBlLnVpbnQ4LCAndWludDgnXSxcbiAgW0RhdGFUeXBlLmJvb2wsICd1aW50OCddLFxuXSk7XG5cbnR5cGUgTUxDb250ZXh0RW50cnkgPSB7XG4gIGdwdURldmljZT86IEdQVURldmljZTtcbiAgb3B0aW9ucz86IE1MQ29udGV4dE9wdGlvbnM7XG4gIG1sQ29udGV4dDogTUxDb250ZXh0O1xufTtcblxuY29uc3QgY29tcGFyZU1MQ29udGV4dE9wdGlvbnMgPSAoYT86IE1MQ29udGV4dE9wdGlvbnMsIGI/OiBNTENvbnRleHRPcHRpb25zKTogYm9vbGVhbiA9PiB7XG4gIGlmIChhID09PSBiKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgaWYgKGEgPT09IHVuZGVmaW5lZCB8fCBiID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgY29uc3QgYUtleXMgPSBPYmplY3Qua2V5cyhhKS5zb3J0KCkgYXMgQXJyYXk8a2V5b2YgdHlwZW9mIGE+O1xuICBjb25zdCBiS2V5cyA9IE9iamVjdC5rZXlzKGIpLnNvcnQoKSBhcyBBcnJheTxrZXlvZiB0eXBlb2YgYj47XG4gIHJldHVybiBhS2V5cy5sZW5ndGggPT09IGJLZXlzLmxlbmd0aCAmJiBhS2V5cy5ldmVyeSgoa2V5LCBpbmRleCkgPT4ga2V5ID09PSBiS2V5c1tpbmRleF0gJiYgYVtrZXldID09PSBiW2tleV0pO1xufTtcblxuLyoqXG4gKiBXZWJOTiBiYWNrZW5kIGltcGxlbWVudGF0aW9uLiBUaGlzIGNsYXNzIGlzIHVzZWQgdG8ga2VlcCB0cmFjayBvZiB0aGUgTUxUZW5zb3JzIGNyZWF0ZWQgYnkgdGhlIGJhY2tlbmQgYW5kIGtlZXAgdHJhY2tcbiAqIG9mIHRoZSBjdXJyZW50IE1MQ29udGV4dCBiZWluZyB1c2VkIGJ5IHRoZSBzZXNzaW9ucy5cbiAqL1xuZXhwb3J0IGNsYXNzIFdlYk5OQmFja2VuZCB7XG4gIC8qKlxuICAgKiBUZW5zb3IgbWFuYWdlcnMgZm9yIGVhY2ggc2Vzc2lvbi5cbiAgICovXG4gIHByaXZhdGUgdGVuc29yTWFuYWdlciA9IGNyZWF0ZVRlbnNvck1hbmFnZXIodGhpcyk7XG4gIC8qKlxuICAgKiBNYXBzIGZyb20gc2Vzc2lvbiBpZCB0byBNTENvbnRleHRzLlxuICAgKi9cbiAgcHJpdmF0ZSBtbENvbnRleHRCeVNlc3Npb25JZCA9IG5ldyBNYXA8bnVtYmVyLCBNTENvbnRleHQ+KCk7XG4gIC8qKlxuICAgKiBNYXBzIGZyb20gTUxDb250ZXh0IHRvIHNlc3Npb24gaWRzLlxuICAgKi9cbiAgcHJpdmF0ZSBzZXNzaW9uSWRzQnlNTENvbnRleHQgPSBuZXcgTWFwPE1MQ29udGV4dCwgU2V0PG51bWJlcj4+KCk7XG4gIC8qKlxuICAgKiBDYWNoZSBvZiBNTENvbnRleHRzLlxuICAgKi9cbiAgcHJpdmF0ZSBtbENvbnRleHRDYWNoZTogTUxDb250ZXh0RW50cnlbXSA9IFtdO1xuICAvKipcbiAgICogQ3VycmVudCBzZXNzaW9uIGlkLlxuICAgKi9cbiAgcHJpdmF0ZSBhY3RpdmVTZXNzaW9uSWQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBNYXBzIGZyb20gc2Vzc2lvbiBpZCB0byBsaXN0IG9mIGdyYXBoIGlucHV0cy5cbiAgICovXG4gIHByaXZhdGUgc2Vzc2lvbkdyYXBoSW5wdXRzOiBNYXA8bnVtYmVyLCBzdHJpbmdbXT4gPSBuZXcgTWFwKCk7XG4gIC8qKlxuICAgKiBNYXBzIGZyb20gc2Vzc2lvbiBpZCB0byBsaXN0IG9mIGdyYXBoIG91dHB1dHMuXG4gICAqL1xuICBwcml2YXRlIHNlc3Npb25HcmFwaE91dHB1dHM6IE1hcDxudW1iZXIsIHN0cmluZ1tdPiA9IG5ldyBNYXAoKTtcbiAgLyoqXG4gICAqIFRlbXBvcmFyeSBncmFwaCBpbnB1dHMgZm9yIHRoZSBjdXJyZW50IHNlc3Npb24uXG4gICAqIFRoZXNlIGlucHV0cyB3aWxsIGJlIHJlZ2lzdGVyZWQgd2hlbiB0aGUgc2Vzc2lvbiBpcyBjcmVhdGVkLlxuICAgKi9cbiAgcHJpdmF0ZSB0ZW1wb3JhcnlHcmFwaElucHV0czogc3RyaW5nW10gPSBbXTtcbiAgLyoqXG4gICAqIFRlbXBvcmFyeSBncmFwaCBvdXRwdXRzIGZvciB0aGUgY3VycmVudCBzZXNzaW9uLlxuICAgKiBUaGVzZSBvdXRwdXRzIHdpbGwgYmUgcmVnaXN0ZXJlZCB3aGVuIHRoZSBzZXNzaW9uIGlzIGNyZWF0ZWQuXG4gICAqL1xuICBwcml2YXRlIHRlbXBvcmFyeUdyYXBoT3V0cHV0czogc3RyaW5nW10gPSBbXTtcbiAgLyoqXG4gICAqIFRlbXBvcmFyeSB0ZW5zb3JzIGZvciB0aGUgY3VycmVudCBzZXNzaW9uLlxuICAgKi9cbiAgcHJpdmF0ZSB0ZW1wb3JhcnlTZXNzaW9uVGVuc29ySWRzOiBNYXA8bnVtYmVyLCBUZW5zb3JJZFtdPiA9IG5ldyBNYXAoKTtcblxuICBjb25zdHJ1Y3RvcihlbnY6IEVudikge1xuICAgIGNvbmZpZ3VyZUxvZ2dlcihlbnYubG9nTGV2ZWwhLCAhIWVudi5kZWJ1Zyk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGN1cnJlbnRTZXNzaW9uSWQoKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy5hY3RpdmVTZXNzaW9uSWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBhY3RpdmUgc2Vzc2lvbicpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5hY3RpdmVTZXNzaW9uSWQ7XG4gIH1cblxuICBwdWJsaWMgb25SdW5TdGFydChzZXNzaW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViTk5dIG9uUnVuU3RhcnQge3Nlc3Npb25JZDogJHtzZXNzaW9uSWR9fWApO1xuICAgIHRoaXMuYWN0aXZlU2Vzc2lvbklkID0gc2Vzc2lvbklkO1xuICB9XG5cbiAgcHVibGljIG9uUnVuRW5kKHNlc3Npb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtXZWJOTl0gb25SdW5FbmQge3Nlc3Npb25JZDogJHtzZXNzaW9uSWR9fWApO1xuICAgIGNvbnN0IHRlbnNvcklkcyA9IHRoaXMudGVtcG9yYXJ5U2Vzc2lvblRlbnNvcklkcy5nZXQoc2Vzc2lvbklkKTtcbiAgICBpZiAoIXRlbnNvcklkcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IHRlbnNvcklkIG9mIHRlbnNvcklkcykge1xuICAgICAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtXZWJOTl0gcmVsZWFzaW5nIHRlbXBvcmFyeSB0ZW5zb3Ige3RlbnNvcklkOiAke3RlbnNvcklkfX1gKTtcbiAgICAgIHRoaXMudGVuc29yTWFuYWdlci5yZWxlYXNlVGVuc29ySWQodGVuc29ySWQpO1xuICAgIH1cbiAgICB0aGlzLnRlbXBvcmFyeVNlc3Npb25UZW5zb3JJZHMuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgdGhpcy5hY3RpdmVTZXNzaW9uSWQgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgY3JlYXRlTUxDb250ZXh0KG9wdGlvbnNPckRldmljZT86IE1MQ29udGV4dE9wdGlvbnMgfCBHUFVEZXZpY2UpOiBQcm9taXNlPE1MQ29udGV4dD4ge1xuICAgIGlmIChvcHRpb25zT3JEZXZpY2UgaW5zdGFuY2VvZiBHUFVEZXZpY2UpIHtcbiAgICAgIGNvbnN0IG1sQ29udGV4dEluZGV4ID0gdGhpcy5tbENvbnRleHRDYWNoZS5maW5kSW5kZXgoKGVudHJ5KSA9PiBlbnRyeS5ncHVEZXZpY2UgPT09IG9wdGlvbnNPckRldmljZSk7XG4gICAgICBpZiAobWxDb250ZXh0SW5kZXggIT09IC0xKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1sQ29udGV4dENhY2hlW21sQ29udGV4dEluZGV4XS5tbENvbnRleHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBtbENvbnRleHQgPSBhd2FpdCBuYXZpZ2F0b3IubWwuY3JlYXRlQ29udGV4dChvcHRpb25zT3JEZXZpY2UpO1xuICAgICAgICB0aGlzLm1sQ29udGV4dENhY2hlLnB1c2goeyBncHVEZXZpY2U6IG9wdGlvbnNPckRldmljZSwgbWxDb250ZXh0IH0pO1xuICAgICAgICByZXR1cm4gbWxDb250ZXh0O1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAob3B0aW9uc09yRGV2aWNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IG1sQ29udGV4dEluZGV4ID0gdGhpcy5tbENvbnRleHRDYWNoZS5maW5kSW5kZXgoXG4gICAgICAgIChlbnRyeSkgPT4gZW50cnkub3B0aW9ucyA9PT0gdW5kZWZpbmVkICYmIGVudHJ5LmdwdURldmljZSA9PT0gdW5kZWZpbmVkLFxuICAgICAgKTtcbiAgICAgIGlmIChtbENvbnRleHRJbmRleCAhPT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWxDb250ZXh0Q2FjaGVbbWxDb250ZXh0SW5kZXhdLm1sQ29udGV4dDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IG1sQ29udGV4dCA9IGF3YWl0IG5hdmlnYXRvci5tbC5jcmVhdGVDb250ZXh0KCk7XG4gICAgICAgIHRoaXMubWxDb250ZXh0Q2FjaGUucHVzaCh7IG1sQ29udGV4dCB9KTtcbiAgICAgICAgcmV0dXJuIG1sQ29udGV4dDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBtbENvbnRleHRJbmRleCA9IHRoaXMubWxDb250ZXh0Q2FjaGUuZmluZEluZGV4KChlbnRyeSkgPT5cbiAgICAgIGNvbXBhcmVNTENvbnRleHRPcHRpb25zKGVudHJ5Lm9wdGlvbnMsIG9wdGlvbnNPckRldmljZSksXG4gICAgKTtcbiAgICBpZiAobWxDb250ZXh0SW5kZXggIT09IC0xKSB7XG4gICAgICByZXR1cm4gdGhpcy5tbENvbnRleHRDYWNoZVttbENvbnRleHRJbmRleF0ubWxDb250ZXh0O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBtbENvbnRleHQgPSBhd2FpdCBuYXZpZ2F0b3IubWwuY3JlYXRlQ29udGV4dChvcHRpb25zT3JEZXZpY2UpO1xuICAgICAgdGhpcy5tbENvbnRleHRDYWNoZS5wdXNoKHsgb3B0aW9uczogb3B0aW9uc09yRGV2aWNlLCBtbENvbnRleHQgfSk7XG4gICAgICByZXR1cm4gbWxDb250ZXh0O1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyByZWdpc3Rlck1MQ29udGV4dChzZXNzaW9uSWQ6IG51bWJlciwgbWxDb250ZXh0OiBNTENvbnRleHQpOiB2b2lkIHtcbiAgICB0aGlzLm1sQ29udGV4dEJ5U2Vzc2lvbklkLnNldChzZXNzaW9uSWQsIG1sQ29udGV4dCk7XG4gICAgbGV0IHNlc3Npb25JZHMgPSB0aGlzLnNlc3Npb25JZHNCeU1MQ29udGV4dC5nZXQobWxDb250ZXh0KTtcbiAgICBpZiAoIXNlc3Npb25JZHMpIHtcbiAgICAgIHNlc3Npb25JZHMgPSBuZXcgU2V0KCk7XG4gICAgICB0aGlzLnNlc3Npb25JZHNCeU1MQ29udGV4dC5zZXQobWxDb250ZXh0LCBzZXNzaW9uSWRzKTtcbiAgICB9XG4gICAgc2Vzc2lvbklkcy5hZGQoc2Vzc2lvbklkKTtcblxuICAgIGlmICh0aGlzLnRlbXBvcmFyeUdyYXBoSW5wdXRzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuc2Vzc2lvbkdyYXBoSW5wdXRzLnNldChzZXNzaW9uSWQsIHRoaXMudGVtcG9yYXJ5R3JhcGhJbnB1dHMpO1xuICAgICAgdGhpcy50ZW1wb3JhcnlHcmFwaElucHV0cyA9IFtdO1xuICAgIH1cbiAgICBpZiAodGhpcy50ZW1wb3JhcnlHcmFwaE91dHB1dHMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5zZXNzaW9uR3JhcGhPdXRwdXRzLnNldChzZXNzaW9uSWQsIHRoaXMudGVtcG9yYXJ5R3JhcGhPdXRwdXRzKTtcbiAgICAgIHRoaXMudGVtcG9yYXJ5R3JhcGhPdXRwdXRzID0gW107XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG9uUmVsZWFzZVNlc3Npb24oc2Vzc2lvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnNlc3Npb25HcmFwaElucHV0cy5kZWxldGUoc2Vzc2lvbklkKTtcbiAgICB0aGlzLnNlc3Npb25HcmFwaE91dHB1dHMuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgY29uc3QgbWxDb250ZXh0ID0gdGhpcy5tbENvbnRleHRCeVNlc3Npb25JZC5nZXQoc2Vzc2lvbklkKSE7XG4gICAgaWYgKCFtbENvbnRleHQpIHtcbiAgICAgIC8vIEN1cnJlbnQgc2Vzc2lvbiBpcyBub3QgYSBXZWJOTiBzZXNzaW9uLlxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnRlbnNvck1hbmFnZXIucmVsZWFzZVRlbnNvcnNGb3JTZXNzaW9uKHNlc3Npb25JZCk7XG4gICAgdGhpcy5tbENvbnRleHRCeVNlc3Npb25JZC5kZWxldGUoc2Vzc2lvbklkKTtcbiAgICBjb25zdCBzZXNzaW9uSWRzID0gdGhpcy5zZXNzaW9uSWRzQnlNTENvbnRleHQuZ2V0KG1sQ29udGV4dCkhO1xuICAgIHNlc3Npb25JZHMuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgaWYgKHNlc3Npb25JZHMuc2l6ZSA9PT0gMCkge1xuICAgICAgdGhpcy5zZXNzaW9uSWRzQnlNTENvbnRleHQuZGVsZXRlKG1sQ29udGV4dCk7XG4gICAgICBjb25zdCBtbENvbnRleHRJbmRleCA9IHRoaXMubWxDb250ZXh0Q2FjaGUuZmluZEluZGV4KChlbnRyeSkgPT4gZW50cnkubWxDb250ZXh0ID09PSBtbENvbnRleHQpO1xuICAgICAgaWYgKG1sQ29udGV4dEluZGV4ICE9PSAtMSkge1xuICAgICAgICB0aGlzLm1sQ29udGV4dENhY2hlLnNwbGljZShtbENvbnRleHRJbmRleCwgMSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGdldE1MQ29udGV4dChzZXNzaW9uSWQ6IG51bWJlcik6IE1MQ29udGV4dCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMubWxDb250ZXh0QnlTZXNzaW9uSWQuZ2V0KHNlc3Npb25JZCk7XG4gIH1cblxuICBwdWJsaWMgcmVzZXJ2ZVRlbnNvcklkKCk6IFRlbnNvcklkIHtcbiAgICByZXR1cm4gdGhpcy50ZW5zb3JNYW5hZ2VyLnJlc2VydmVUZW5zb3JJZCgpO1xuICB9XG5cbiAgcHVibGljIHJlbGVhc2VUZW5zb3JJZCh0ZW5zb3JJZDogVGVuc29ySWQpOiB2b2lkIHtcbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW1dlYk5OXSByZWxlYXNlVGVuc29ySWQge3RlbnNvcklkOiAke3RlbnNvcklkfX1gKTtcbiAgICB0aGlzLnRlbnNvck1hbmFnZXIucmVsZWFzZVRlbnNvcklkKHRlbnNvcklkKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBlbnN1cmVUZW5zb3IoXG4gICAgc2Vzc2lvbklkOiBudW1iZXIgfCB1bmRlZmluZWQsXG4gICAgdGVuc29ySWQ6IFRlbnNvcklkLFxuICAgIG9ubnhEYXRhVHlwZTogRGF0YVR5cGUsXG4gICAgZGltZW5zaW9uczogbnVtYmVyW10sXG4gICAgY29weU9sZDogYm9vbGVhbixcbiAgKTogUHJvbWlzZTxNTFRlbnNvcj4ge1xuICAgIGNvbnN0IHdlYm5uRGF0YVR5cGUgPSBvbm54RGF0YVR5cGVUb1dlYm5uRGF0YVR5cGUuZ2V0KG9ubnhEYXRhVHlwZSk7XG4gICAgaWYgKCF3ZWJubkRhdGFUeXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIE9OTlggZGF0YSB0eXBlOiAke29ubnhEYXRhVHlwZX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudGVuc29yTWFuYWdlci5lbnN1cmVUZW5zb3IoXG4gICAgICBzZXNzaW9uSWQgPz8gdGhpcy5jdXJyZW50U2Vzc2lvbklkLFxuICAgICAgdGVuc29ySWQsXG4gICAgICB3ZWJubkRhdGFUeXBlLFxuICAgICAgZGltZW5zaW9ucyxcbiAgICAgIGNvcHlPbGQsXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBjcmVhdGVUZW1wb3JhcnlUZW5zb3IoXG4gICAgc2Vzc2lvbklkOiBudW1iZXIsXG4gICAgb25ueERhdGFUeXBlOiBEYXRhVHlwZSxcbiAgICBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gICk6IFByb21pc2U8VGVuc29ySWQ+IHtcbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW1dlYk5OXSBjcmVhdGVUZW1wb3JhcnlUZW5zb3Ige29ubnhEYXRhVHlwZTogJHtvbm54RGF0YVR5cGV9LCBzaGFwZTogJHtzaGFwZX19YCk7XG4gICAgY29uc3QgZGF0YVR5cGUgPSBvbm54RGF0YVR5cGVUb1dlYm5uRGF0YVR5cGUuZ2V0KG9ubnhEYXRhVHlwZSk7XG4gICAgaWYgKCFkYXRhVHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBPTk5YIGRhdGEgdHlwZTogJHtvbm54RGF0YVR5cGV9YCk7XG4gICAgfVxuICAgIGNvbnN0IHRlbnNvcklkID0gdGhpcy50ZW5zb3JNYW5hZ2VyLnJlc2VydmVUZW5zb3JJZCgpO1xuICAgIGF3YWl0IHRoaXMudGVuc29yTWFuYWdlci5lbnN1cmVUZW5zb3Ioc2Vzc2lvbklkLCB0ZW5zb3JJZCwgZGF0YVR5cGUsIHNoYXBlLCBmYWxzZSk7XG4gICAgY29uc3QgdGVuc29ySWRzID0gdGhpcy50ZW1wb3JhcnlTZXNzaW9uVGVuc29ySWRzLmdldChzZXNzaW9uSWQpO1xuICAgIGlmICghdGVuc29ySWRzKSB7XG4gICAgICB0aGlzLnRlbXBvcmFyeVNlc3Npb25UZW5zb3JJZHMuc2V0KHNlc3Npb25JZCwgW3RlbnNvcklkXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRlbnNvcklkcy5wdXNoKHRlbnNvcklkKTtcbiAgICB9XG4gICAgcmV0dXJuIHRlbnNvcklkO1xuICB9XG5cbiAgcHVibGljIHVwbG9hZFRlbnNvcih0ZW5zb3JJZDogVGVuc29ySWQsIGRhdGE6IFVpbnQ4QXJyYXkpOiB2b2lkIHtcbiAgICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgICBpZiAoIXdhc20uc2hvdWxkVHJhbnNmZXJUb01MVGVuc29yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RyeWluZyB0byB1cGxvYWQgdG8gYSBNTFRlbnNvciB3aGlsZSBzaG91bGRUcmFuc2ZlclRvTUxUZW5zb3IgaXMgZmFsc2UnKTtcbiAgICB9XG4gICAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtXZWJOTl0gdXBsb2FkVGVuc29yIHt0ZW5zb3JJZDogJHt0ZW5zb3JJZH0sIGRhdGE6ICR7ZGF0YS5ieXRlTGVuZ3RofX1gKTtcbiAgICB0aGlzLnRlbnNvck1hbmFnZXIudXBsb2FkKHRlbnNvcklkLCBkYXRhKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBkb3dubG9hZFRlbnNvcih0ZW5zb3JJZDogVGVuc29ySWQsIGRzdEJ1ZmZlcjogQXJyYXlCdWZmZXJWaWV3IHwgQXJyYXlCdWZmZXIpOiBQcm9taXNlPHVuZGVmaW5lZD4ge1xuICAgIHJldHVybiB0aGlzLnRlbnNvck1hbmFnZXIuZG93bmxvYWQodGVuc29ySWQsIGRzdEJ1ZmZlcik7XG4gIH1cblxuICBwdWJsaWMgY3JlYXRlTUxUZW5zb3JEb3dubG9hZGVyKHRlbnNvcklkOiBUZW5zb3JJZCwgdHlwZTogVGVuc29yLk1MVGVuc29yRGF0YVR5cGVzKTogKCkgPT4gUHJvbWlzZTxUZW5zb3IuRGF0YVR5cGU+IHtcbiAgICByZXR1cm4gYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMudGVuc29yTWFuYWdlci5kb3dubG9hZCh0ZW5zb3JJZCk7XG4gICAgICByZXR1cm4gY3JlYXRlVmlldyhkYXRhLCB0eXBlKTtcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIHJlZ2lzdGVyTUxUZW5zb3Ioc2Vzc2lvbklkOiBudW1iZXIsIHRlbnNvcjogTUxUZW5zb3IsIG9ubnhEYXRhVHlwZTogRGF0YVR5cGUsIGRpbWVuc2lvbnM6IG51bWJlcltdKTogVGVuc29ySWQge1xuICAgIGNvbnN0IHdlYm5uRGF0YVR5cGUgPSBvbm54RGF0YVR5cGVUb1dlYm5uRGF0YVR5cGUuZ2V0KG9ubnhEYXRhVHlwZSk7XG4gICAgaWYgKCF3ZWJubkRhdGFUeXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIE9OTlggZGF0YSB0eXBlOiAke29ubnhEYXRhVHlwZX1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBpZCA9IHRoaXMudGVuc29yTWFuYWdlci5yZWdpc3RlclRlbnNvcihzZXNzaW9uSWQsIHRlbnNvciwgd2Vibm5EYXRhVHlwZSwgZGltZW5zaW9ucyk7XG4gICAgTE9HX0RFQlVHKFxuICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgKCkgPT5cbiAgICAgICAgYFtXZWJOTl0gcmVnaXN0ZXJNTFRlbnNvciB7dGVuc29yOiAke3RlbnNvcn0sIGRhdGFUeXBlOiAke3dlYm5uRGF0YVR5cGV9LCBkaW1lbnNpb25zOiAke1xuICAgICAgICAgIGRpbWVuc2lvbnNcbiAgICAgICAgfX0gLT4ge3RlbnNvcklkOiAke2lkfX1gLFxuICAgICk7XG4gICAgcmV0dXJuIGlkO1xuICB9XG5cbiAgLy8gUmVnaXN0ZXIgYSBXZWJOTiBDb25zdGFudCBvcGVyYW5kIGZyb20gZXh0ZXJuYWwgZGF0YS5cbiAgcHVibGljIHJlZ2lzdGVyTUxDb25zdGFudChcbiAgICBleHRlcm5hbEZpbGVQYXRoOiBzdHJpbmcsXG4gICAgZGF0YU9mZnNldDogbnVtYmVyLFxuICAgIGRhdGFMZW5ndGg6IG51bWJlcixcbiAgICBidWlsZGVyOiBNTEdyYXBoQnVpbGRlcixcbiAgICBkZXNjOiBNTE9wZXJhbmREZXNjcmlwdG9yLFxuICAgIG1vdW50ZWRGaWxlczogTWFwPHN0cmluZywgVWludDhBcnJheT4gfCB1bmRlZmluZWQsXG4gICAgc2hvdWxkQ29udmVydEludDY0VG9JbnQzMiA9IGZhbHNlLFxuICApOiBNTE9wZXJhbmQge1xuICAgIC8vIElmIGF2YWlsYWJsZSwgXCJNb2R1bGUuTW91bnRlZEZpbGVzXCIgaXMgYSBNYXAgZm9yIGFsbCBwcmVsb2FkZWQgZmlsZXMuXG4gICAgaWYgKCFtb3VudGVkRmlsZXMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRXh0ZXJuYWwgbW91bnRlZCBmaWxlcyBhcmUgbm90IGF2YWlsYWJsZS4nKTtcbiAgICB9XG5cbiAgICBsZXQgZmlsZVBhdGggPSBleHRlcm5hbEZpbGVQYXRoO1xuICAgIGlmIChleHRlcm5hbEZpbGVQYXRoLnN0YXJ0c1dpdGgoJy4vJykpIHtcbiAgICAgIGZpbGVQYXRoID0gZXh0ZXJuYWxGaWxlUGF0aC5zdWJzdHJpbmcoMik7XG4gICAgfVxuICAgIGNvbnN0IGZpbGVEYXRhID0gbW91bnRlZEZpbGVzLmdldChmaWxlUGF0aCk7XG4gICAgaWYgKCFmaWxlRGF0YSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGaWxlIHdpdGggbmFtZSAke2ZpbGVQYXRofSBub3QgZm91bmQgaW4gcHJlbG9hZGVkIGZpbGVzLmApO1xuICAgIH1cblxuICAgIGlmIChkYXRhT2Zmc2V0ICsgZGF0YUxlbmd0aCA+IGZpbGVEYXRhLmJ5dGVMZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT3V0IG9mIGJvdW5kczogZGF0YSBvZmZzZXQgYW5kIGxlbmd0aCBleGNlZWQgdGhlIGV4dGVybmFsIGZpbGUgZGF0YSBzaXplLicpO1xuICAgIH1cblxuICAgIGNvbnN0IGJ1ZmZlciA9IGZpbGVEYXRhLnNsaWNlKGRhdGFPZmZzZXQsIGRhdGFPZmZzZXQgKyBkYXRhTGVuZ3RoKS5idWZmZXI7XG4gICAgbGV0IGJ1ZmZlclZpZXc6IEFycmF5QnVmZmVyVmlldztcbiAgICBzd2l0Y2ggKGRlc2MuZGF0YVR5cGUpIHtcbiAgICAgIGNhc2UgJ2Zsb2F0MzInOlxuICAgICAgICBidWZmZXJWaWV3ID0gbmV3IEZsb2F0MzJBcnJheShidWZmZXIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2Zsb2F0MTYnOlxuICAgICAgICBidWZmZXJWaWV3ID1cbiAgICAgICAgICB0eXBlb2YgRmxvYXQxNkFycmF5ICE9PSAndW5kZWZpbmVkJyAmJiBGbG9hdDE2QXJyYXkuZnJvbSA/IG5ldyBGbG9hdDE2QXJyYXkoYnVmZmVyKSA6IG5ldyBVaW50MTZBcnJheShidWZmZXIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2ludDMyJzpcbiAgICAgICAgYnVmZmVyVmlldyA9IG5ldyBJbnQzMkFycmF5KGJ1ZmZlcik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndWludDMyJzpcbiAgICAgICAgYnVmZmVyVmlldyA9IG5ldyBVaW50MzJBcnJheShidWZmZXIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2ludDY0JzpcbiAgICAgICAgaWYgKHNob3VsZENvbnZlcnRJbnQ2NFRvSW50MzIpIHtcbiAgICAgICAgICAvLyBJbnQ2NCBpcyBub3Qgc3VwcG9ydGVkIGJ5IGN1cnJlbnQgY29udGV4dCwgdXNlIGludDMyIGluc3RlYWQuXG4gICAgICAgICAgY29uc3QgaW50MzJCdWZmZXIgPSBjb252ZXJ0RGF0YVRvSW50MzIobmV3IFVpbnQ4QXJyYXkoYnVmZmVyKSwgJ2ludDY0Jyk7XG4gICAgICAgICAgYnVmZmVyVmlldyA9IG5ldyBJbnQzMkFycmF5KGludDMyQnVmZmVyLmJ1ZmZlcik7XG4gICAgICAgICAgZGVzYy5kYXRhVHlwZSA9ICdpbnQzMic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYnVmZmVyVmlldyA9IG5ldyBCaWdJbnQ2NEFycmF5KGJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd1aW50NjQnOlxuICAgICAgICBidWZmZXJWaWV3ID0gbmV3IEJpZ1VpbnQ2NEFycmF5KGJ1ZmZlcik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaW50OCc6XG4gICAgICAgIGJ1ZmZlclZpZXcgPSBuZXcgSW50OEFycmF5KGJ1ZmZlcik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaW50NCc6XG4gICAgICBjYXNlICd1aW50NCc6XG4gICAgICBjYXNlICd1aW50OCc6XG4gICAgICAgIGJ1ZmZlclZpZXcgPSBuZXcgVWludDhBcnJheShidWZmZXIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke2Rlc2MuZGF0YVR5cGV9IGluIGNyZWF0aW5nIFdlYk5OIENvbnN0YW50IGZyb20gZXh0ZXJuYWwgZGF0YS5gKTtcbiAgICB9XG5cbiAgICBMT0dfREVCVUcoXG4gICAgICAndmVyYm9zZScsXG4gICAgICAoKSA9PlxuICAgICAgICBgW1dlYk5OXSByZWdpc3Rlck1MQ29uc3RhbnQge2RhdGFUeXBlOiAke2Rlc2MuZGF0YVR5cGV9LCBzaGFwZTogJHtkZXNjLnNoYXBlfX19ICR7XG4gICAgICAgICAgc2hvdWxkQ29udmVydEludDY0VG9JbnQzMiA/ICcoTm90ZTogaXQgd2FzIGludDY0IGRhdGEgdHlwZSBhbmQgcmVnaXN0ZXJlZCB0byBpbnQzMiBhcyB3b3JrYXJvdW5kKScgOiAnJ1xuICAgICAgICB9YCxcbiAgICApO1xuXG4gICAgcmV0dXJuIGJ1aWxkZXIuY29uc3RhbnQoZGVzYywgYnVmZmVyVmlldyk7XG4gIH1cblxuICBwdWJsaWMgcmVnaXN0ZXJHcmFwaElucHV0KGlucHV0TmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy50ZW1wb3JhcnlHcmFwaElucHV0cy5wdXNoKGlucHV0TmFtZSk7XG4gIH1cblxuICBwdWJsaWMgcmVnaXN0ZXJHcmFwaE91dHB1dChvdXRwdXROYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnRlbXBvcmFyeUdyYXBoT3V0cHV0cy5wdXNoKG91dHB1dE5hbWUpO1xuICB9XG5cbiAgcHVibGljIGlzR3JhcGhJbnB1dChzZXNzaW9uSWQ6IG51bWJlciwgaW5wdXROYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBpbnB1dE5hbWVzID0gdGhpcy5zZXNzaW9uR3JhcGhJbnB1dHMuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKCFpbnB1dE5hbWVzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBpbnB1dE5hbWVzLmluY2x1ZGVzKGlucHV0TmFtZSk7XG4gIH1cblxuICBwdWJsaWMgaXNHcmFwaE91dHB1dChzZXNzaW9uSWQ6IG51bWJlciwgb3V0cHV0TmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgb3V0cHV0TmFtZXMgPSB0aGlzLnNlc3Npb25HcmFwaE91dHB1dHMuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKCFvdXRwdXROYW1lcykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gb3V0cHV0TmFtZXMuaW5jbHVkZXMob3V0cHV0TmFtZSk7XG4gIH1cblxuICBwdWJsaWMgaXNHcmFwaElucHV0T3V0cHV0VHlwZVN1cHBvcnRlZChzZXNzaW9uSWQ6IG51bWJlciwgdHlwZTogVGVuc29yLlR5cGUsIGlzSW5wdXQgPSB0cnVlKTogYm9vbGVhbiB7XG4gICAgY29uc3QgY29udGV4dCA9IHRoaXMubWxDb250ZXh0QnlTZXNzaW9uSWQuZ2V0KHNlc3Npb25JZCk7XG4gICAgY29uc3QgZGF0YVR5cGUgPSBvbm54RGF0YVR5cGVUb1dlYm5uRGF0YVR5cGUuZ2V0KHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtKHR5cGUpKTtcblxuICAgIGlmICh0eXBlb2YgZGF0YVR5cGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKGlzSW5wdXQpIHtcbiAgICAgIHJldHVybiAhIWNvbnRleHQ/Lm9wU3VwcG9ydExpbWl0cygpLmlucHV0LmRhdGFUeXBlcy5pbmNsdWRlcyhkYXRhVHlwZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAhIWNvbnRleHQ/Lm9wU3VwcG9ydExpbWl0cygpLm91dHB1dC5kYXRhVHlwZXMuaW5jbHVkZXMoZGF0YVR5cGUpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBmbHVzaCgpOiB2b2lkIHtcbiAgICAvLyBVbmxpa2UgdGhlIFdlYkdQVSBiYWNrZW5kLCB0aGUgV2ViTk4gYmFja2VuZCBkb2VzIG5vdCBuZWVkIHRvIGZsdXNoIGFueSBwZW5kaW5nIG9wZXJhdGlvbnMuXG4gIH1cbn1cbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vdGVuc29yLXZpZXcnO1xuXG5pbXBvcnQgeyBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL29wcy9jb21tb24nO1xuXG5leHBvcnQgdHlwZSBTZXNzaW9uU3RhdGUgPSAnZGVmYXVsdCcgfCAnY2FwdHVyaW5nJyB8ICdyZXBsYXlpbmcnO1xuXG5leHBvcnQgZW51bSBHcHVEYXRhVHlwZSB7XG4gIGRlZmF1bHQgPSAwLFxuICB1cGxvYWQgPSAxLFxuICBwcm9maWxlID0gMixcbn1cbmV4cG9ydCB0eXBlIEdwdURhdGFJZCA9IG51bWJlcjtcblxuZXhwb3J0IHR5cGUgR3B1QXJjaGl0ZWN0dXJlID0gJ2FtcGVyZScgfCAnZ2VuLTEybHAnO1xuZXhwb3J0IHR5cGUgR3B1VmVuZG9yID0gJ2FtZCcgfCAnaW50ZWwnIHwgJ252aWRpYSc7XG5leHBvcnQgaW50ZXJmYWNlIEFkYXB0ZXJJbmZvIHtcbiAgaXNBcmNoaXRlY3R1cmU6IChhcmNoaXRlY3R1cmU6IEdwdUFyY2hpdGVjdHVyZSkgPT4gYm9vbGVhbjtcbiAgaXNWZW5kb3I6ICh2ZW5kb3I6IEdwdVZlbmRvcikgPT4gYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHcHVEYXRhIHtcbiAgdHlwZTogR3B1RGF0YVR5cGU7XG4gIGlkOiBHcHVEYXRhSWQ7XG4gIGJ1ZmZlcjogR1BVQnVmZmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvckluZm8ge1xuICBkaW1zOiByZWFkb25seSBudW1iZXJbXTtcbiAgZGF0YVR5cGU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcm9ncmFtVW5pZm9ybSB7XG4gIHR5cGU6IERhdGFUeXBlO1xuICBkYXRhOiBudW1iZXIgfCByZWFkb25seSBudW1iZXJbXTtcbn1cblxuZXhwb3J0IHR5cGUgUHJvZ3JhbVVuaWZvcm1WYXJpYWJsZUluZm8gPSBbdHlwZTogRGF0YVR5cGUsIGxlbmd0aDogbnVtYmVyXTtcblxuLyoqXG4gKiBSZXByZXNlbnQgdGhlIGRlcGVuZGVuY3kgb2YgYSBwcm9ncmFtIG9uIGEgc3BlY2lmaWMgaW5wdXQgdGVuc29yLlxuICpcbiAqIC0gJ25vbmUnOiB0aGUgc2hhZGVyL3VuaWZvcm0gZG9lcyBub3QgZGVwZW5kIG9uIHRoaXMgaW5wdXQncyBpbmZvXG4gKiAtICd0eXBlJzogdGhlIHNoYWRlci91bmlmb3JtIGRlcGVuZHMgb24gZGF0YSB0eXBlIG9mIHRoaXMgaW5wdXRcbiAqIC0gJ3JhbmsnOiB0aGUgc2hhZGVyL3VuaWZvcm0gZGVwZW5kcyBvbiBkYXRhIHR5cGUgYW5kIHRoZSByYW5rIG9mIHRoaXMgaW5wdXRcbiAqIC0gJ2RpbXMnOiB0aGUgc2hhZGVyL3VuaWZvcm0gZGVwZW5kcyBvbiBkYXRhIHR5cGUgYW5kIHRoZSBkaW1zIG9mIHRoaXMgaW5wdXRcbiAqIC0gJ2RhdGEnOiB0aGUgc2hhZGVyL3VuaWZvcm0gZGVwZW5kcyBvbiBkYXRhIHR5cGUsIHRoZSBkaW1zIGFuZCB0aGUgZGF0YSBvZiB0aGlzIGlucHV0XG4gKi9cbmV4cG9ydCB0eXBlIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5ID0gJ25vbmUnIHwgJ3R5cGUnIHwgJ3JhbmsnIHwgJ2RpbXMnIHwgJ2RhdGEnO1xuXG4vKipcbiAqIFJlcHJlc2VudCBpbmZvcm1hdGlvbiBhYm91dCBhIHByb2dyYW0ncyBjYWNoZSBmb3Igc2hhZGVyLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFByb2dyYW1TaGFkZXJDYWNoZUluZm8ge1xuICAvKipcbiAgICogYW4gb3B0aW9uYWwgc3RyaW5nIGFzIGEgY2FjaGUgaGludCBpbiB0aGUgYXJ0aWZhY3QgY2FjaGUuIElmIHRoaXMgaXMgbm90IHNwZWNpZmllZCwgdGhlIGNhY2hlIGhpbnQgd2lsbCBiZSBlbXB0eS5cbiAgICpcbiAgICogVGhpcyBoaW50IHN0cmluZyBzaG91bGQgb25seSBjb250YWlucyBpbml0aWFsaXppbmctdGltZSBpbmZvcm1hdGlvbiwgc3VjaCBhcyB0aGUgYXR0cmlidXRlcyBvciBhbnkgaW5mb3JtYXRpb24gb2ZcbiAgICogaW5pdGlhbGl6ZXJzLiBJdCBzaG91bGQgTk9UIGNvbnRhaW4gYW55IHJ1bnRpbWUgaW5mb3JtYXRpb24sIHN1Y2ggYXMgdGhlIHNoYXBlIG9mIGlucHV0cy5cbiAgICovXG4gIGhpbnQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIGFuIG9wdGlvbmFsIGxpc3Qgb2YgZGVwZW5kZW5jaWVzIG9mIHRoZSBwcm9ncmFtIG9uIHRoZSBpbnB1dCB0ZW5zb3JzLiBJZiB0aGlzIGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBwcm9ncmFtIGRlcGVuZHNcbiAgICogb24gJ2RpbXMnIG9mIGFsbCBpbnB1dHMuXG4gICAqL1xuICBpbnB1dERlcGVuZGVuY2llcz86IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W107XG59XG5cbi8qKlxuICogUmVwcmVzZW50IGluZm9ybWF0aW9uIGFib3V0IGEgcHJvZ3JhbSdzIGNhY2hlIGZvciB1bmlmb3JtLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFByb2dyYW1Vbmlmb3JtQ2FjaGVJbmZvIHtcbiAgLyoqXG4gICAqIGFuIG9wdGlvbmFsIHN0cmluZyBhcyBhIGNhY2hlIGhpbnQgaW4gdGhlIHVuaWZvcm0gY2FjaGUuIElmIHRoaXMgaXMgbm90IHNwZWNpZmllZCwgdGhlIGNhY2hlIGhpbnQgd2lsbCBiZSBlbXB0eS5cbiAgICpcbiAgICogVGhpcyBoaW50IHN0cmluZyBzaG91bGQgb25seSBjb250YWlucyBydW50aW1lIGluZm9ybWF0aW9uLCBzdWNoIGFzIHRoZSBzaGFwZSBvZiBpbnB1dHMuXG4gICAqL1xuICBoaW50Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBhbiBvcHRpb25hbCBsaXN0IG9mIGRlcGVuZGVuY2llcyBvZiB0aGUgcHJvZ3JhbSBvbiB0aGUgaW5wdXQgdGVuc29ycy4gSWYgdGhpcyBpcyBub3Qgc3BlY2lmaWVkLCB0aGUgcHJvZ3JhbSBkZXBlbmRzXG4gICAqIG9uICdub25lJyBvZiBhbGwgaW5wdXRzLlxuICAgKi9cbiAgaW5wdXREZXBlbmRlbmNpZXM/OiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdO1xufVxuXG4vKipcbiAqIEEgc2V0IG9mIGRhdGEgdGhhdCByZXByZXNlbnQgYSBzaGFkZXIgcHJvZ3JhbVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFByb2dyYW1JbmZvIHtcbiAgLyoqXG4gICAqIHRoZSBuYW1lIG9mIHRoZSBwcm9ncmFtLiB1c2VkIGZvciBkZWJ1Z2dpbmcgYW5kIHByb2ZpbGluZ1xuICAgKi9cbiAgbmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBhbiBvcHRpb25hbCBvYmplY3QgZGVzY3JpYmluZyB0aGUgY2FjaGUgaW5mb3JtYXRpb24gb2YgdGhlIHByb2dyYW0gc2hhZGVyLlxuICAgKlxuICAgKiBJZiB0aGlzIGlzIG5vdCBzcGVjaWZpZWQsIGFzc3VtZSBoaW50IGlzIGVtcHR5IGFuZCBpbnB1dERlcGVuZGVuY2llcyBhcmUgWydkaW1zJ10gZm9yIGFsbCBpbnB1dHMuXG4gICAqL1xuICBzaGFkZXJDYWNoZT86IFByb2dyYW1TaGFkZXJDYWNoZUluZm87XG5cbiAgLyoqXG4gICAqIHRoZSBzaGFkZXIncyBwcm9jZXNzaW5nIHNvdXJjZSBjb2RlLlxuICAgKlxuICAgKiBUaGlzIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIHdoZW4gc2hhZGVyIGNhY2hlIG1pc3NlZC5cbiAgICovXG4gIGdldFNoYWRlclNvdXJjZTogKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgZnVuY3Rpb24gdG8gZ2V0IHJ1biBkYXRhIHJlcXVpcmVkIHRvIHJ1biB0aGUgcHJvZ3JhbS5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBldmVyeSB0aW1lIHRoZSBwcm9ncmFtIGlzIGV4ZWN1dGVkLiBTaG91bGQga2VlcCB0aGlzIGZ1bmN0aW9uIGFzIHNpbXBsZSBhcyBwb3NzaWJsZS5cbiAgICovXG4gIGdldFJ1bkRhdGE6IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSkgPT4ge1xuICAgIG91dHB1dHM6IHJlYWRvbmx5IFRlbnNvckluZm9bXTtcbiAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IG51bWJlcjsgeT86IG51bWJlcjsgej86IG51bWJlciB9O1xuICAgIHByb2dyYW1Vbmlmb3Jtcz86IHJlYWRvbmx5IFByb2dyYW1Vbmlmb3JtW107XG4gIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXJ0aWZhY3Qge1xuICBwcm9ncmFtSW5mbzogUHJvZ3JhbUluZm87XG4gIGNvbXB1dGVQaXBlbGluZTogR1BVQ29tcHV0ZVBpcGVsaW5lO1xuICB1bmlmb3JtVmFyaWFibGVzSW5mbzogcmVhZG9ubHkgUHJvZ3JhbVVuaWZvcm1WYXJpYWJsZUluZm9bXSB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb21wdXRlQ29udGV4dElucHV0c091dHB1dHNNYXBwaW5nIHtcbiAgLyoqXG4gICAqIHNwZWNpZnkgdGhlIG1hcHBpbmcgdG8gdGhlIHByb2dyYW0ncyBpbnB1dHMuIHRoZSB2YWx1ZSBjYW4gYmUgYSBudW1iZXIgb3IgYSB0ZW5zb3Igdmlldy5cbiAgICogLSBpZiBpdCdzIGEgbnVtYmVyLCBpdCdzIHRoZSBpbmRleCBvZiB0aGUga2VybmVsJ3MgaW5wdXRcbiAgICogLSBpZiBpdCdzIGEgdGVuc29yIHZpZXcsIGl0J3MgYW4gZXhpc3RpbmcgdGVuc29yIHZpZXcgdGhhdCB3aWxsIGJlIHVzZWQgYXMgdGhlIGlucHV0XG4gICAqXG4gICAqIGlmIGlucHV0cyBpcyBub3Qgc3BlY2lmaWVkLCB0aGUgbWFwcGluZyB3aWxsIGJlIHRoZSBrZXJuZWwncyBpbnB1dHMgaW4gb3JkZXIuXG4gICAqL1xuICByZWFkb25seSBpbnB1dHM/OiBSZWFkb25seUFycmF5PFRlbnNvclZpZXcgfCBudW1iZXI+O1xuICAvKipcbiAgICogc3BlY2lmeSB0aGUgbWFwcGluZyB0byB0aGUgcHJvZ3JhbSdzIG91dHB1dHMuIHRoZSB2YWx1ZSBtdXN0IGJlIGEgbnVtYmVyLlxuICAgKiAtIGlmIGl0J3MgYSBub24tbmVnYXRpdmUgbnVtYmVyLCBpdCdzIHRoZSBpbmRleCBvZiB0aGUga2VybmVsJ3Mgb3V0cHV0XG4gICAqIC0gaWYgaXQncyAtMSwgaXQncyBhbiBvdXRwdXQgdGhhdCB3aWxsIGJlIGNyZWF0ZWQgYXMgYSB0ZW1wb3JhcnkgdmFsdWUuIHRoaXMgdmFsdWUgd2lsbCBiZSByZWxlYXNlZCBhZnRlclxuICAgKiB0aGUga2VybmVsIGlzIGV4ZWN1dGVkLlxuICAgKiAtIGlmIGl0J3MgLTIsIGl0J3MgYW4gb3V0cHV0IHRoYXQgd2lsbCBiZSBjcmVhdGVkIGFzIGEgcGVyc2lzdGVudCB2YWx1ZS4gdGhpcyB2YWx1ZSB3aWxsIGJlIHJlbGVhc2VkIHdoZW4gdGhlXG4gICAqIGtlcm5lbCBpcyByZWxlYXNlZC5cbiAgICpcbiAgICogaWYgb3V0cHV0cyBpcyBub3Qgc3BlY2lmaWVkLCB0aGUgbWFwcGluZyB3aWxsIGJlIHRoZSBrZXJuZWwncyBvdXRwdXRzIGluIG9yZGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0cz86IHJlYWRvbmx5IG51bWJlcltdO1xufVxuXG4vKipcbiAqIEEgQ29tcHV0ZUNvbnRleHQgaW5zdGFuY2UgY2FycmllcyB0aGUgc3RhdGVzIHRoYXQgcmVwcmVzZW50aW5nIHRoZSBjdXJyZW50IHJ1bm5pbmcgb2YgYSBrZXJuZWwuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcHV0ZUNvbnRleHQge1xuICAvKipcbiAgICogZ3B1IGFkYXB0ZXIgaW5mb1xuICAgKi9cbiAgcmVhZG9ubHkgYWRhcHRlckluZm86IEFkYXB0ZXJJbmZvO1xuXG4gIC8qKlxuICAgKiBzdG9yZXMgdGhlIHBvaW50ZXIgdG8gT3BLZXJuZWxDb250ZXh0XG4gICAqL1xuICByZWFkb25seSBvcEtlcm5lbENvbnRleHQ6IG51bWJlcjtcblxuICAvKipcbiAgICogYSBsaXN0IG9mIGlucHV0cywgZWFjaCBpbnB1dCBpcyBhbiBpbnN0YW5jZSBvZiBUZW5zb3JWaWV3XG4gICAqL1xuICByZWFkb25seSBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXTtcblxuICAvKipcbiAgICogYSBjdXN0b20gZGF0YSBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCB0byBzdG9yZSBhbnkgZGF0YSB0aGF0IGlzIG5lZWRlZCBieSB0aGUga2VybmVsXG4gICAqL1xuICByZWFkb25seSBrZXJuZWxDdXN0b21EYXRhOiB7IFtrZXk6IHN0cmluZ106IHVua25vd24gfTtcblxuICAvKipcbiAgICogYSBidWZmZXIgdGhhdCBjYW4gYmUgdXNlZCB0byBhY2Nlc3MgY3VzdG9tIGRhdGEgY3JlYXRlZCBlYWNoIHRpbWUgdGhlIGtlcm5lbCBpcyBleGVjdXRlZFxuICAgKi9cbiAgcmVhZG9ubHkgY3VzdG9tRGF0YUJ1ZmZlcjogVWludDhBcnJheTtcblxuICAvKipcbiAgICogYSBudW1iZXIgb2Ygb3V0cHV0cyBmb3IgdGhlIG5vZGVcbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dENvdW50OiBudW1iZXI7XG5cbiAgY29tcHV0ZShwcm9ncmFtOiBQcm9ncmFtSW5mbywgaW5wdXRzT3V0cHV0c01hcHBpbmc/OiBDb21wdXRlQ29udGV4dElucHV0c091dHB1dHNNYXBwaW5nKTogVGVuc29yVmlld1tdO1xuICBvdXRwdXQoaW5kZXg6IG51bWJlciwgZGltczogcmVhZG9ubHkgbnVtYmVyW10pOiBudW1iZXI7XG59XG5cbmV4cG9ydCB0eXBlIFRpbWVzdGFtcFF1ZXJ5ID0gJ25vbmUnIHwgJ2luc2lkZS1wYXNzZXMnIHwgJ2F0LXBhc3Nlcyc7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFdlYkdwdUJhY2tlbmQgfSBmcm9tICcuLi9iYWNrZW5kLXdlYmdwdSc7XG5pbXBvcnQgeyBMT0dfREVCVUcgfSBmcm9tICcuLi9sb2cnO1xuXG5pbXBvcnQgeyBHcHVEYXRhLCBHcHVEYXRhSWQsIEdwdURhdGFUeXBlIH0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogbWFuYWdlcyBHcHVEYXRhSWQgLT4gR3B1QnVmZmVyXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR3B1RGF0YU1hbmFnZXIge1xuICAvKipcbiAgICogY29weSBkYXRhIGZyb20gQ1BVIHRvIEdQVS5cbiAgICovXG4gIHVwbG9hZChpZDogR3B1RGF0YUlkLCBkYXRhOiBVaW50OEFycmF5KTogdm9pZDtcbiAgLyoqXG4gICAqIGNvcHkgZGF0YSBmcm9tIEdQVSB0byBHUFUuXG4gICAqL1xuICBtZW1jcHkoc291cmNlSWQ6IEdwdURhdGFJZCwgZGVzdGluYXRpb25JZDogR3B1RGF0YUlkKTogdm9pZDtcbiAgLyoqXG4gICAqIGNyZWF0ZSBuZXcgZGF0YSBvbiBHUFUuXG4gICAqL1xuICBjcmVhdGUoc2l6ZTogbnVtYmVyLCB1c2FnZT86IG51bWJlcik6IEdwdURhdGE7XG4gIC8qKlxuICAgKiBnZXQgR1BVIGRhdGEgYnkgSUQuXG4gICAqL1xuICBnZXQoaWQ6IEdwdURhdGFJZCk6IEdwdURhdGEgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiByZWxlYXNlIHRoZSBkYXRhIG9uIEdQVSBieSBJRC5cbiAgICpcbiAgICogQHJldHVybiBzaXplIG9mIHRoZSBkYXRhIHJlbGVhc2VkXG4gICAqL1xuICByZWxlYXNlKGlkOiBHcHVEYXRhSWQpOiBudW1iZXI7XG4gIC8qKlxuICAgKiBjb3B5IGRhdGEgZnJvbSBHUFUgdG8gQ1BVLlxuICAgKi9cbiAgZG93bmxvYWQoaWQ6IEdwdURhdGFJZCwgZ2V0VGFyZ2V0QnVmZmVyOiAoKSA9PiBVaW50OEFycmF5KTogUHJvbWlzZTx2b2lkPjtcblxuICAvKipcbiAgICogcmVmcmVzaCB0aGUgYnVmZmVycyB0aGF0IG1hcmtlZCBmb3IgcmVsZWFzZS5cbiAgICpcbiAgICogd2hlbiByZWxlYXNlKCkgaXMgY2FsbGVkLCB0aGUgYnVmZmVyIGlzIG5vdCByZWxlYXNlZCBpbW1lZGlhdGVseS4gdGhpcyBpcyBiZWNhdXNlIHdlIG5lZWQgdG8gd2FpdCBmb3IgdGhlIGNvbW1hbmRzXG4gICAqIHRvIGJlIHN1Ym1pdHRlZCB0byB0aGUgR1BVLiB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBhZnRlciB0aGUgY29tbWFuZHMgYXJlIHN1Ym1pdHRlZCBzbyB0aGF0IHRoZSBidWZmZXJzIGNhbiBiZVxuICAgKiBhY3R1YWxseSByZWxlYXNlZC5cbiAgICovXG4gIHJlZnJlc2hQZW5kaW5nQnVmZmVycygpOiB2b2lkO1xuXG4gIC8qKlxuICAgKiByZWdpc3RlciBhbiBleHRlcm5hbCBidWZmZXIgZm9yIElPIEJpbmRpbmcuIElmIHRoZSBidWZmZXIgaXMgYWxyZWFkeSByZWdpc3RlcmVkLCByZXR1cm4gdGhlIGV4aXN0aW5nIEdQVSBkYXRhIElELlxuICAgKlxuICAgKiBHUFUgZGF0YSBtYW5hZ2VyIG9ubHkgbWFuYWdlcyBhIG1hcHBpbmcgYmV0d2VlbiB0aGUgYnVmZmVyIGFuZCB0aGUgR1BVIGRhdGEgSUQuIEl0IHdpbGwgbm90IG1hbmFnZSB0aGUgbGlmZWN5Y2xlIG9mXG4gICAqIHRoZSBleHRlcm5hbCBidWZmZXIuXG4gICAqL1xuICByZWdpc3RlckV4dGVybmFsQnVmZmVyKGJ1ZmZlcjogR1BVQnVmZmVyLCBvcmlnaW5hbFNpemU6IG51bWJlciwgcHJldmlvdXM/OiBbR3B1RGF0YUlkLCBHUFVCdWZmZXJdKTogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiB1bnJlZ2lzdGVyIGFuIGV4dGVybmFsIGJ1ZmZlciBmb3IgSU8gQmluZGluZy5cbiAgICovXG4gIHVucmVnaXN0ZXJFeHRlcm5hbEJ1ZmZlcihpZDogR3B1RGF0YUlkKTogdm9pZDtcblxuICAvKipcbiAgICogZGVzdHJveSBhbGwgZ3B1IGJ1ZmZlcnMuXG4gICAqL1xuICBkaXNwb3NlKCk6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIGNyZWF0ZSBzZXNzaW9uIHJlbGF0ZWQgZGF0YS5cbiAgICovXG4gIG9uQ3JlYXRlU2Vzc2lvbigpOiB2b2lkO1xuXG4gIC8qKlxuICAgKiByZWxlYXNlIHNlc3Npb24gcmVsYXRlZCBkYXRhLlxuICAgKiBAcGFyYW0gc2Vzc2lvbklkIC0gc3BlY2lmeSB0aGUgc2Vzc2lvbiBJRC5cbiAgICovXG4gIG9uUmVsZWFzZVNlc3Npb24oc2Vzc2lvbklkOiBudW1iZXIpOiB2b2lkO1xufVxuXG5pbnRlcmZhY2UgU3RvcmFnZUNhY2hlVmFsdWUge1xuICBncHVEYXRhOiBHcHVEYXRhO1xuICBvcmlnaW5hbFNpemU6IG51bWJlcjtcbn1cblxuY29uc3QgYnVja2V0RnJlZWxpc3Q6IE1hcDxudW1iZXIsIG51bWJlcj4gPSBuZXcgTWFwKFtcbiAgWzY0LCAyNTBdLFxuICBbMTI4LCAyMDBdLFxuICBbMjU2LCAyMDBdLFxuICBbNTEyLCAyMDBdLFxuICBbMjA0OCwgMjMwXSxcbiAgWzQwOTYsIDIwMF0sXG4gIFs4MTkyLCA1MF0sXG4gIFsxNjM4NCwgNTBdLFxuICBbMzI3NjgsIDUwXSxcbiAgWzY1NTM2LCA1MF0sXG4gIFsxMzEwNzIsIDUwXSxcbiAgWzI2MjE0NCwgNTBdLFxuICBbNTI0Mjg4LCA1MF0sXG4gIFsxMDQ4NTc2LCA1MF0sXG4gIFsyMDk3MTUyLCAzMF0sXG4gIFs0MTk0MzA0LCAyMF0sXG4gIFs4Mzg4NjA4LCAxMF0sXG4gIFsxMjU4MjkxMiwgMTBdLFxuICBbMTY3NzcyMTYsIDEwXSxcbiAgWzI2MjE0NDAwLCAxNV0sXG4gIFszMzU1NDQzMiwgMjJdLFxuICBbNDQyMzY4MDAsIDJdLFxuICBbNTg5ODI0MDAsIDZdLFxuICAvLyB3ZSBkb24ndCB3YW50IHRvIGNhY2hlIHRoZSBidWNrZXQgc2l6ZXMgYmVsb3cgYnV0IG5vdCBjYWNoaW5nIHRoZW1cbiAgLy8gcmVzdWx0cyBpbiBzb21lIG1ham9yIHBlcmZvcm1hbmNlIGhpdHMgZm9yIG1vZGVscyBsaWtlIHNkLXR1cmJvLlxuICBbNjcxMDg4NjQsIDZdLFxuICBbMTM0MjE3NzI4LCA2XSxcbiAgWzE2Nzc3MjE2MCwgNl0sXG5dKTtcblxuY29uc3QgYnVja2V0QXJyOiBudW1iZXJbXSA9IFtdO1xuXG4vKipcbiAqIG5vcm1hbGl6ZSB0aGUgYnVmZmVyIHNpemUgc28gdGhhdCBpdCBmaXRzIHRoZSAxMjgtYml0cyAoMTYgYnl0ZXMpIGFsaWdubWVudC5cbiAqL1xuY29uc3QgY2FsY05vcm1hbGl6ZWRCdWZmZXJTaXplID0gKHNpemU6IG51bWJlcikgPT4gTWF0aC5jZWlsKE51bWJlcihzaXplKSAvIDE2KSAqIDE2O1xuXG4vKipcbiAqIGNhbGN1bGF0ZSB0aGUgYnVmZmVyIHNpemUgc28gdGhhdCBpdCBmaXRzIGludG8gYnVja2V0cy5cbiAqL1xuY29uc3QgY2FsY0J1Y2tldEJ1ZmZlclNpemUgPSAoc2l6ZTogbnVtYmVyKSA9PiB7XG4gIGZvciAobGV0IGlkeCA9IDA7IGlkeCA8IGJ1Y2tldEFyci5sZW5ndGg7IGlkeCsrKSB7XG4gICAgY29uc3Qgc2l6ZUZvckJ1Y2tldCA9IGJ1Y2tldEFycltpZHhdO1xuICAgIGlmIChzaXplIDw9IHNpemVGb3JCdWNrZXQpIHtcbiAgICAgIHJldHVybiBzaXplRm9yQnVja2V0O1xuICAgIH1cbiAgfVxuICAvLyBub3QgaW4gYnVja2V0IGxpc3QgLT4gY2FsbGVyIHdpbGwgbm90IGNhY2hlLCByb3VuZCB1cCB0byAxNi5cbiAgcmV0dXJuIE1hdGguY2VpbChzaXplIC8gMTYpICogMTY7XG59O1xuXG5sZXQgZ3VpZCA9IDE7XG5jb25zdCBjcmVhdGVOZXdHcHVEYXRhSWQgPSAoKSA9PiBndWlkKys7XG5cbi8qKlxuICogZXhwb3J0ZWQgc3RhbmRhcmQgZG93bmxvYWQgZnVuY3Rpb24uIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCBieSB0aGUgc2Vzc2lvbiB0byBkb3dubG9hZCB0aGUgZGF0YSBmcm9tIEdQVSwgYW5kIGFsc28gYnlcbiAqIGZhY3RvcnkgdG8gY3JlYXRlIEdQVSB0ZW5zb3JzIHdpdGggdGhlIGNhcGFjaXR5IG9mIGRvd25sb2FkaW5nIGRhdGEgZnJvbSBHUFUuXG4gKlxuICogQHBhcmFtIGJhY2tlbmQgLSB0aGUgV2ViR1BVIGJhY2tlbmRcbiAqIEBwYXJhbSBncHVCdWZmZXIgLSB0aGUgR1BVIGJ1ZmZlciB0byBkb3dubG9hZFxuICogQHBhcmFtIG9yaWdpbmFsU2l6ZSAtIHRoZSBvcmlnaW5hbCBzaXplIG9mIHRoZSBkYXRhXG4gKiBAcGFyYW0gZ2V0VGFyZ2V0QnVmZmVyIC0gb3B0aW9uYWwuIElmIHByb3ZpZGVkLCB0aGUgZGF0YSB3aWxsIGJlIGNvcGllZCB0byB0aGUgdGFyZ2V0IGJ1ZmZlci4gT3RoZXJ3aXNlLCBhIG5ldyBidWZmZXJcbiAqIHdpbGwgYmUgY3JlYXRlZCBhbmQgcmV0dXJuZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBkb3dubG9hZEdwdURhdGEgPSBhc3luYyAoXG4gIGJhY2tlbmQ6IFdlYkdwdUJhY2tlbmQsXG4gIGdwdUJ1ZmZlcjogR1BVQnVmZmVyLFxuICBvcmlnaW5hbFNpemU6IG51bWJlcixcbiAgZ2V0VGFyZ2V0QnVmZmVyPzogKCkgPT4gVWludDhBcnJheSxcbik6IFByb21pc2U8VWludDhBcnJheT4gPT4ge1xuICBjb25zdCBidWZmZXJTaXplID0gY2FsY05vcm1hbGl6ZWRCdWZmZXJTaXplKG9yaWdpbmFsU2l6ZSk7XG4gIGNvbnN0IGdwdVJlYWRCdWZmZXIgPSBiYWNrZW5kLmRldmljZS5jcmVhdGVCdWZmZXIoXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICB7IHNpemU6IGJ1ZmZlclNpemUsIHVzYWdlOiBHUFVCdWZmZXJVc2FnZS5DT1BZX0RTVCB8IEdQVUJ1ZmZlclVzYWdlLk1BUF9SRUFEIH0sXG4gICk7XG4gIHRyeSB7XG4gICAgY29uc3QgY29tbWFuZEVuY29kZXIgPSBiYWNrZW5kLmdldENvbW1hbmRFbmNvZGVyKCk7XG4gICAgYmFja2VuZC5lbmRDb21wdXRlUGFzcygpO1xuICAgIGNvbW1hbmRFbmNvZGVyLmNvcHlCdWZmZXJUb0J1ZmZlcihcbiAgICAgIGdwdUJ1ZmZlciAvKiBzb3VyY2UgYnVmZmVyICovLFxuICAgICAgMCAvKiBzb3VyY2Ugb2Zmc2V0ICovLFxuICAgICAgZ3B1UmVhZEJ1ZmZlciAvKiBkZXN0aW5hdGlvbiBidWZmZXIgKi8sXG4gICAgICAwIC8qIGRlc3RpbmF0aW9uIG9mZnNldCAqLyxcbiAgICAgIGJ1ZmZlclNpemUgLyogc2l6ZSAqLyxcbiAgICApO1xuICAgIGJhY2tlbmQuZmx1c2goKTtcblxuICAgIGF3YWl0IGdwdVJlYWRCdWZmZXIubWFwQXN5bmMoR1BVTWFwTW9kZS5SRUFEKTtcblxuICAgIGNvbnN0IGFycmF5QnVmZmVyID0gZ3B1UmVhZEJ1ZmZlci5nZXRNYXBwZWRSYW5nZSgpO1xuICAgIGlmIChnZXRUYXJnZXRCdWZmZXIpIHtcbiAgICAgIC8vIGlmIHdlIGFscmVhZHkgaGF2ZSBhIENQVSBidWZmZXIgdG8gYWNjZXB0IHRoZSBkYXRhLCBubyBuZWVkIHRvIGNsb25lIHRoZSBBcnJheUJ1ZmZlci5cbiAgICAgIGNvbnN0IHRhcmdldEJ1ZmZlciA9IGdldFRhcmdldEJ1ZmZlcigpO1xuICAgICAgdGFyZ2V0QnVmZmVyLnNldChuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlciwgMCwgb3JpZ2luYWxTaXplKSk7XG4gICAgICByZXR1cm4gdGFyZ2V0QnVmZmVyO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyB0aGUgbWFwcGVkIEFycmF5QnVmZmVyIHdpbGwgYmUgcmVsZWFzZWQgd2hlbiB0aGUgR1BVIGJ1ZmZlciBpcyBkZXN0cm95ZWQuIE5lZWQgdG8gY2xvbmUgdGhlXG4gICAgICAvLyBBcnJheUJ1ZmZlci5cbiAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlci5zbGljZSgwLCBvcmlnaW5hbFNpemUpKTtcbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgZ3B1UmVhZEJ1ZmZlci5kZXN0cm95KCk7XG4gIH1cbn07XG5cbmNsYXNzIEdwdURhdGFNYW5hZ2VySW1wbCBpbXBsZW1lbnRzIEdwdURhdGFNYW5hZ2VyIHtcbiAgLy8gR1BVIERhdGEgSUQgPT4gR1BVIERhdGEgKCBzdG9yYWdlIGJ1ZmZlciApXG4gIHByaXZhdGUgc3RvcmFnZUNhY2hlOiBNYXA8R3B1RGF0YUlkLCBTdG9yYWdlQ2FjaGVWYWx1ZT47XG5cbiAgLy8gcGVuZGluZyBidWZmZXJzIGZvciBjb21wdXRpbmdcbiAgcHJpdmF0ZSBidWZmZXJzUGVuZGluZzogR1BVQnVmZmVyW107XG5cbiAgLy8gVGhlIHJldXNhYmxlIHN0b3JhZ2UgYnVmZmVycyBmb3IgY29tcHV0aW5nLlxuICBwcml2YXRlIGZyZWVCdWZmZXJzOiBNYXA8bnVtYmVyLCBHUFVCdWZmZXJbXT47XG4gIC8vIFRoZSByZXVzYWJsZSB1bmlmb3JtIGJ1ZmZlcnNcbiAgcHJpdmF0ZSBmcmVlVW5pZm9ybUJ1ZmZlcnM6IE1hcDxudW1iZXIsIEdQVUJ1ZmZlcltdPjtcblxuICAvLyBUaGUgcGVuZGluZ0J1ZmZlcnMgZm9yIGNhcHR1cmUgZ3JhcGguXG4gIC8vIGEgU2Vzc2lvbklEIC0+IEdQVUJ1ZmZlcltdIG1hcHBpbmcuXG4gIHByaXZhdGUgY2FwdHVyZWRQZW5kaW5nQnVmZmVyczogTWFwPG51bWJlciwgR1BVQnVmZmVyW10+O1xuXG4gIC8vIFRoZSBzZXNzaW9uIGNvdW50LlxuICBwcml2YXRlIHNlc3Npb25Db3VudDogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgYmFja2VuZDogV2ViR3B1QmFja2VuZCkge1xuICAgIHRoaXMuc3RvcmFnZUNhY2hlID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZnJlZUJ1ZmZlcnMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mcmVlVW5pZm9ybUJ1ZmZlcnMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5idWZmZXJzUGVuZGluZyA9IFtdO1xuICAgIHRoaXMuY2FwdHVyZWRQZW5kaW5nQnVmZmVycyA9IG5ldyBNYXAoKTtcblxuICAgIGZvciAoY29uc3QgW2tleV0gb2YgYnVja2V0RnJlZWxpc3QpIHtcbiAgICAgIGJ1Y2tldEFyci5wdXNoKGtleSk7XG4gICAgICB0aGlzLmZyZWVCdWZmZXJzLnNldChrZXksIFtdKTtcbiAgICAgIHRoaXMuZnJlZVVuaWZvcm1CdWZmZXJzLnNldChrZXksIFtdKTtcbiAgICB9XG5cbiAgICB0aGlzLnNlc3Npb25Db3VudCA9IDA7XG4gIH1cblxuICB1cGxvYWQoaWQ6IEdwdURhdGFJZCwgZGF0YTogVWludDhBcnJheSk6IHZvaWQge1xuICAgIGNvbnN0IHNyY0FycmF5QnVmZmVyID0gZGF0YS5idWZmZXI7XG4gICAgY29uc3Qgc3JjT2Zmc2V0ID0gZGF0YS5ieXRlT2Zmc2V0O1xuICAgIGNvbnN0IHNyY0xlbmd0aCA9IGRhdGEuYnl0ZUxlbmd0aDtcbiAgICBjb25zdCBzaXplID0gY2FsY05vcm1hbGl6ZWRCdWZmZXJTaXplKHNyY0xlbmd0aCk7XG5cbiAgICAvLyBnZXQgZGVzdGluYXRpb24gZ3B1IGJ1ZmZlclxuICAgIGNvbnN0IGdwdURhdGFDYWNoZSA9IHRoaXMuc3RvcmFnZUNhY2hlLmdldChpZCk7XG4gICAgaWYgKCFncHVEYXRhQ2FjaGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ3B1IGRhdGEgZm9yIHVwbG9hZGluZyBkb2VzIG5vdCBleGlzdCcpO1xuICAgIH1cbiAgICBpZiAoTnVtYmVyKGdwdURhdGFDYWNoZS5vcmlnaW5hbFNpemUpICE9PSBzcmNMZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW5jb25zaXN0ZW50IGRhdGEgc2l6ZS4gZ3B1IGRhdGEgc2l6ZT0ke2dwdURhdGFDYWNoZS5vcmlnaW5hbFNpemV9LCBkYXRhIHNpemU9JHtzcmNMZW5ndGh9YCk7XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIGdwdSBidWZmZXJcbiAgICBjb25zdCBncHVCdWZmZXJGb3JVcGxvYWRpbmcgPSB0aGlzLmJhY2tlbmQuZGV2aWNlLmNyZWF0ZUJ1ZmZlcihcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgICB7IG1hcHBlZEF0Q3JlYXRpb246IHRydWUsIHNpemUsIHVzYWdlOiBHUFVCdWZmZXJVc2FnZS5NQVBfV1JJVEUgfCBHUFVCdWZmZXJVc2FnZS5DT1BZX1NSQyB9LFxuICAgICk7XG5cbiAgICAvLyBjb3B5ICh1cGxvYWQpIGRhdGFcbiAgICBjb25zdCBhcnJheUJ1ZmZlciA9IGdwdUJ1ZmZlckZvclVwbG9hZGluZy5nZXRNYXBwZWRSYW5nZSgpO1xuICAgIG5ldyBVaW50OEFycmF5KGFycmF5QnVmZmVyKS5zZXQobmV3IFVpbnQ4QXJyYXkoc3JjQXJyYXlCdWZmZXIsIHNyY09mZnNldCwgc3JjTGVuZ3RoKSk7XG4gICAgZ3B1QnVmZmVyRm9yVXBsb2FkaW5nLnVubWFwKCk7XG5cbiAgICAvLyBHUFUgY29weVxuICAgIGNvbnN0IGNvbW1hbmRFbmNvZGVyID0gdGhpcy5iYWNrZW5kLmRldmljZS5jcmVhdGVDb21tYW5kRW5jb2RlcigpO1xuICAgIGNvbW1hbmRFbmNvZGVyLmNvcHlCdWZmZXJUb0J1ZmZlcihncHVCdWZmZXJGb3JVcGxvYWRpbmcsIDAsIGdwdURhdGFDYWNoZS5ncHVEYXRhLmJ1ZmZlciwgMCwgc2l6ZSk7XG4gICAgdGhpcy5iYWNrZW5kLmRldmljZS5xdWV1ZS5zdWJtaXQoW2NvbW1hbmRFbmNvZGVyLmZpbmlzaCgpXSk7XG4gICAgZ3B1QnVmZmVyRm9yVXBsb2FkaW5nLmRlc3Ryb3koKTtcblxuICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViR1BVXSBHcHVEYXRhTWFuYWdlci51cGxvYWQoaWQ9JHtpZH0pYCk7XG4gIH1cblxuICBtZW1jcHkoc291cmNlSWQ6IEdwdURhdGFJZCwgZGVzdGluYXRpb25JZDogR3B1RGF0YUlkKTogdm9pZCB7XG4gICAgLy8gZ2V0IHNvdXJjZSBncHUgYnVmZmVyXG4gICAgY29uc3Qgc291cmNlR3B1RGF0YUNhY2hlID0gdGhpcy5zdG9yYWdlQ2FjaGUuZ2V0KHNvdXJjZUlkKTtcbiAgICBpZiAoIXNvdXJjZUdwdURhdGFDYWNoZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzb3VyY2UgZ3B1IGRhdGEgZm9yIG1lbWNweSBkb2VzIG5vdCBleGlzdCcpO1xuICAgIH1cbiAgICAvLyBnZXQgZGVzdGluYXRpb24gZ3B1IGJ1ZmZlclxuICAgIGNvbnN0IGRlc3RpbmF0aW9uR3B1RGF0YUNhY2hlID0gdGhpcy5zdG9yYWdlQ2FjaGUuZ2V0KGRlc3RpbmF0aW9uSWQpO1xuICAgIGlmICghZGVzdGluYXRpb25HcHVEYXRhQ2FjaGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZGVzdGluYXRpb24gZ3B1IGRhdGEgZm9yIG1lbWNweSBkb2VzIG5vdCBleGlzdCcpO1xuICAgIH1cbiAgICBpZiAoc291cmNlR3B1RGF0YUNhY2hlLm9yaWdpbmFsU2l6ZSAhPT0gZGVzdGluYXRpb25HcHVEYXRhQ2FjaGUub3JpZ2luYWxTaXplKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2luY29uc2lzdGVudCBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGdwdSBkYXRhIHNpemUnKTtcbiAgICB9XG5cbiAgICBjb25zdCBzaXplID0gY2FsY05vcm1hbGl6ZWRCdWZmZXJTaXplKHNvdXJjZUdwdURhdGFDYWNoZS5vcmlnaW5hbFNpemUpO1xuXG4gICAgLy8gR1BVIGNvcHlcbiAgICBjb25zdCBjb21tYW5kRW5jb2RlciA9IHRoaXMuYmFja2VuZC5nZXRDb21tYW5kRW5jb2RlcigpO1xuICAgIHRoaXMuYmFja2VuZC5lbmRDb21wdXRlUGFzcygpO1xuICAgIGNvbW1hbmRFbmNvZGVyLmNvcHlCdWZmZXJUb0J1ZmZlcihcbiAgICAgIHNvdXJjZUdwdURhdGFDYWNoZS5ncHVEYXRhLmJ1ZmZlcixcbiAgICAgIDAsXG4gICAgICBkZXN0aW5hdGlvbkdwdURhdGFDYWNoZS5ncHVEYXRhLmJ1ZmZlcixcbiAgICAgIDAsXG4gICAgICBzaXplLFxuICAgICk7XG4gIH1cblxuICByZWdpc3RlckV4dGVybmFsQnVmZmVyKGJ1ZmZlcjogR1BVQnVmZmVyLCBvcmlnaW5hbFNpemU6IG51bWJlciwgcHJldmlvdXM/OiBbR3B1RGF0YUlkLCBHUFVCdWZmZXJdKTogbnVtYmVyIHtcbiAgICBsZXQgaWQ6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgIGlkID0gcHJldmlvdXNbMF07XG4gICAgICBpZiAoYnVmZmVyID09PSBwcmV2aW91c1sxXSkge1xuICAgICAgICBMT0dfREVCVUcoXG4gICAgICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgICAgICgpID0+XG4gICAgICAgICAgICBgW1dlYkdQVV0gR3B1RGF0YU1hbmFnZXIucmVnaXN0ZXJFeHRlcm5hbEJ1ZmZlcihzaXplPSR7b3JpZ2luYWxTaXplfSkgPT4gaWQ9JHtpZH0sIGJ1ZmZlciBpcyB0aGUgc2FtZSwgc2tpcC5gLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gaWQ7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuYmFja2VuZC5jYXB0dXJlZENvbW1hbmRMaXN0Lmhhcyh0aGlzLmJhY2tlbmQuY3VycmVudFNlc3Npb25JZCEpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgUmVnaXN0ZXJpbmcgYSBkaWZmZXJlbnQgZXh0ZXJuYWwgYnVmZmVyIHVuZGVyIGdyYXBoIGNhcHR1cmUgbW9kZSBpcyBub3Qgc3VwcG9ydGVkIHlldC5cbiAgICAgICAgICAgICBQbGVhc2UgdXNlIHRoZSBwcmV2aW91cyBleHRlcm5hbCBidWZmZXIhYCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlkID0gY3JlYXRlTmV3R3B1RGF0YUlkKCk7XG4gICAgfVxuXG4gICAgdGhpcy5zdG9yYWdlQ2FjaGUuc2V0KGlkLCB7IGdwdURhdGE6IHsgaWQsIHR5cGU6IEdwdURhdGFUeXBlLmRlZmF1bHQsIGJ1ZmZlciB9LCBvcmlnaW5hbFNpemUgfSk7XG4gICAgTE9HX0RFQlVHKFxuICAgICAgJ3ZlcmJvc2UnLFxuICAgICAgKCkgPT4gYFtXZWJHUFVdIEdwdURhdGFNYW5hZ2VyLnJlZ2lzdGVyRXh0ZXJuYWxCdWZmZXIoc2l6ZT0ke29yaWdpbmFsU2l6ZX0pID0+IGlkPSR7aWR9LCByZWdpc3RlcmVkLmAsXG4gICAgKTtcbiAgICByZXR1cm4gaWQ7XG4gIH1cblxuICB1bnJlZ2lzdGVyRXh0ZXJuYWxCdWZmZXIoaWQ6IEdwdURhdGFJZCk6IHZvaWQge1xuICAgIGlmIChpZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLnN0b3JhZ2VDYWNoZS5kZWxldGUoaWQpO1xuICAgICAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtXZWJHUFVdIEdwdURhdGFNYW5hZ2VyLnVucmVnaXN0ZXJFeHRlcm5hbEJ1ZmZlcigpID0+IGlkPSR7aWR9YCk7XG4gICAgfVxuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgY3JlYXRlKHNpemU6IG51bWJlciwgdXNhZ2UgPSBHUFVCdWZmZXJVc2FnZS5TVE9SQUdFIHwgR1BVQnVmZmVyVXNhZ2UuQ09QWV9TUkMgfCBHUFVCdWZmZXJVc2FnZS5DT1BZX0RTVCk6IEdwdURhdGEge1xuICAgIGNvbnN0IGJ1ZmZlclNpemUgPSBjYWxjQnVja2V0QnVmZmVyU2l6ZShzaXplKTtcblxuICAgIGxldCBncHVCdWZmZXI7XG4gICAgLy8gQ3VycmVudGx5LCBvbmx5IHN0b3JhZ2UgYnVmZmVycyBhcmUgcmV1c2VkLlxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgY29uc3QgaXNTdG9yYWdlID0gKHVzYWdlICYgR1BVQnVmZmVyVXNhZ2UuU1RPUkFHRSkgPT09IEdQVUJ1ZmZlclVzYWdlLlNUT1JBR0U7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICBjb25zdCBpc1VuaWZvcm0gPSAodXNhZ2UgJiBHUFVCdWZmZXJVc2FnZS5VTklGT1JNKSA9PT0gR1BVQnVmZmVyVXNhZ2UuVU5JRk9STTtcbiAgICBpZiAoaXNTdG9yYWdlIHx8IGlzVW5pZm9ybSkge1xuICAgICAgY29uc3QgZnJlZUJ1ZmZlcnMgPSBpc1N0b3JhZ2UgPyB0aGlzLmZyZWVCdWZmZXJzIDogdGhpcy5mcmVlVW5pZm9ybUJ1ZmZlcnM7XG4gICAgICBjb25zdCBidWZmZXJzID0gZnJlZUJ1ZmZlcnMuZ2V0KGJ1ZmZlclNpemUpO1xuICAgICAgaWYgKCFidWZmZXJzKSB7XG4gICAgICAgIC8vIG5vIHN1Y2ggYnVja2V0L2ZyZWVsaXN0IC0gY3JlYXRlIGdwdSBidWZmZXJcbiAgICAgICAgZ3B1QnVmZmVyID0gdGhpcy5iYWNrZW5kLmRldmljZS5jcmVhdGVCdWZmZXIoeyBzaXplOiBidWZmZXJTaXplLCB1c2FnZSB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChidWZmZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAvLyBpbiBmcmVlbGlzdCwgdXNlIGl0XG4gICAgICAgICAgZ3B1QnVmZmVyID0gYnVmZmVycy5wb3AoKSBhcyBHUFVCdWZmZXI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gYnVja2V0IGVtcHR5LCBjcmVhdGUgZ3B1IGJ1ZmZlclxuICAgICAgICAgIGdwdUJ1ZmZlciA9IHRoaXMuYmFja2VuZC5kZXZpY2UuY3JlYXRlQnVmZmVyKHsgc2l6ZTogYnVmZmVyU2l6ZSwgdXNhZ2UgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gY3JlYXRlIGdwdSBidWZmZXJcbiAgICAgIGdwdUJ1ZmZlciA9IHRoaXMuYmFja2VuZC5kZXZpY2UuY3JlYXRlQnVmZmVyKHsgc2l6ZTogYnVmZmVyU2l6ZSwgdXNhZ2UgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgZ3B1RGF0YSA9IHsgaWQ6IGNyZWF0ZU5ld0dwdURhdGFJZCgpLCB0eXBlOiBHcHVEYXRhVHlwZS5kZWZhdWx0LCBidWZmZXI6IGdwdUJ1ZmZlciB9O1xuICAgIHRoaXMuc3RvcmFnZUNhY2hlLnNldChncHVEYXRhLmlkLCB7IGdwdURhdGEsIG9yaWdpbmFsU2l6ZTogTnVtYmVyKHNpemUpIH0pO1xuXG4gICAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtXZWJHUFVdIEdwdURhdGFNYW5hZ2VyLmNyZWF0ZShzaXplPSR7c2l6ZX0pID0+IGlkPSR7Z3B1RGF0YS5pZH1gKTtcbiAgICByZXR1cm4gZ3B1RGF0YTtcbiAgfVxuXG4gIGdldChpZDogR3B1RGF0YUlkKTogR3B1RGF0YSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmFnZUNhY2hlLmdldChpZCk/LmdwdURhdGE7XG4gIH1cblxuICByZWxlYXNlKGlkSW5wdXQ6IEdwdURhdGFJZCk6IG51bWJlciB7XG4gICAgY29uc3QgaWQgPSB0eXBlb2YgaWRJbnB1dCA9PT0gJ2JpZ2ludCcgPyBOdW1iZXIoaWRJbnB1dCkgOiBpZElucHV0O1xuICAgIGNvbnN0IGNhY2hlZERhdGEgPSB0aGlzLnN0b3JhZ2VDYWNoZS5nZXQoaWQpO1xuICAgIGlmICghY2FjaGVkRGF0YSkge1xuICAgICAgaWYgKHRoaXMuc3RvcmFnZUNhY2hlLnNpemUgPT09IDApIHtcbiAgICAgICAgLy8gY2FjaGUgd2FzIHByZXZpb3VzbHkgY2xlYXJlZCwgbm8gbmVlZCB0byByZWxlYXNlIGFueXRoaW5nLlxuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigncmVsZWFzaW5nIGRhdGEgZG9lcyBub3QgZXhpc3QnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW1dlYkdQVV0gR3B1RGF0YU1hbmFnZXIucmVsZWFzZShpZD0ke2lkfSksIGdwdURhdGFJZD0ke2NhY2hlZERhdGEuZ3B1RGF0YS5pZH1gKTtcblxuICAgIHRoaXMuc3RvcmFnZUNhY2hlLmRlbGV0ZShpZCk7XG4gICAgdGhpcy5idWZmZXJzUGVuZGluZy5wdXNoKGNhY2hlZERhdGEuZ3B1RGF0YS5idWZmZXIpO1xuICAgIC8vIGNhY2hlZERhdGEuZ3B1RGF0YS5idWZmZXIuZGVzdHJveSgpO1xuXG4gICAgcmV0dXJuIGNhY2hlZERhdGEub3JpZ2luYWxTaXplO1xuICB9XG5cbiAgYXN5bmMgZG93bmxvYWQoaWQ6IEdwdURhdGFJZCwgZ2V0VGFyZ2V0QnVmZmVyOiAoKSA9PiBVaW50OEFycmF5KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY2FjaGVkRGF0YSA9IHRoaXMuc3RvcmFnZUNhY2hlLmdldChOdW1iZXIoaWQpKTtcbiAgICBpZiAoIWNhY2hlZERhdGEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZGF0YSBkb2VzIG5vdCBleGlzdCcpO1xuICAgIH1cbiAgICBhd2FpdCBkb3dubG9hZEdwdURhdGEodGhpcy5iYWNrZW5kLCBjYWNoZWREYXRhLmdwdURhdGEuYnVmZmVyLCBjYWNoZWREYXRhLm9yaWdpbmFsU2l6ZSwgZ2V0VGFyZ2V0QnVmZmVyKTtcbiAgfVxuXG4gIHJlZnJlc2hQZW5kaW5nQnVmZmVycygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5idWZmZXJzUGVuZGluZy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5iYWNrZW5kLnNlc3Npb25TdGF0dXMgPT09ICdkZWZhdWx0Jykge1xuICAgICAgZm9yIChjb25zdCBidWZmZXIgb2YgdGhpcy5idWZmZXJzUGVuZGluZykge1xuICAgICAgICBjb25zdCBtYXhJbkZyZWVMaXN0ID0gYnVja2V0RnJlZWxpc3QuZ2V0KGJ1ZmZlci5zaXplKTtcblxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgICAgICBpZiAoKGJ1ZmZlci51c2FnZSAmIEdQVUJ1ZmZlclVzYWdlLlNUT1JBR0UpID09PSBHUFVCdWZmZXJVc2FnZS5TVE9SQUdFKSB7XG4gICAgICAgICAgLy8gUHV0IHRoZSBwZW5kaW5nIGJ1ZmZlciB0byBmcmVlQnVmZmVycyBsaXN0IGluc3RlYWQgb2YgcmVhbGx5IGRlc3Ryb3lpbmcgaXQgZm9yIGJ1ZmZlciByZXVzaW5nLlxuICAgICAgICAgIGNvbnN0IGZyZWVsaXN0ID0gdGhpcy5mcmVlQnVmZmVycy5nZXQoYnVmZmVyLnNpemUpIHx8IFtdO1xuICAgICAgICAgIGlmIChtYXhJbkZyZWVMaXN0ID09PSB1bmRlZmluZWQgfHwgZnJlZWxpc3QubGVuZ3RoID49IG1heEluRnJlZUxpc3QpIHtcbiAgICAgICAgICAgIGJ1ZmZlci5kZXN0cm95KCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZyZWVsaXN0LnB1c2goYnVmZmVyKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICAgICAgfSBlbHNlIGlmICgoYnVmZmVyLnVzYWdlICYgR1BVQnVmZmVyVXNhZ2UuVU5JRk9STSkgPT09IEdQVUJ1ZmZlclVzYWdlLlVOSUZPUk0pIHtcbiAgICAgICAgICAvLyBQdXQgdGhlIHBlbmRpbmcgYnVmZmVyIHRvIGZyZWVVbmlmb3JtQnVmZmVycyBsaXN0IGluc3RlYWQgb2YgcmVhbGx5IGRlc3Ryb3lpbmcgaXQgZm9yIGJ1ZmZlciByZXVzaW5nLlxuICAgICAgICAgIGNvbnN0IGZyZWVsaXN0ID0gdGhpcy5mcmVlVW5pZm9ybUJ1ZmZlcnMuZ2V0KGJ1ZmZlci5zaXplKSB8fCBbXTtcbiAgICAgICAgICBpZiAobWF4SW5GcmVlTGlzdCA9PT0gdW5kZWZpbmVkIHx8IGZyZWVsaXN0Lmxlbmd0aCA+PSBtYXhJbkZyZWVMaXN0KSB7XG4gICAgICAgICAgICBidWZmZXIuZGVzdHJveSgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmcmVlbGlzdC5wdXNoKGJ1ZmZlcik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGJ1ZmZlci5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMuYnVmZmVyc1BlbmRpbmcgPSBbXTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRG9uJ3QgcmVsZWFzZSBpbnRlcm1lZGlhdGUgdGVuc29ycyBpbiBub24tZGVmYXVsdCBtb2RlLlxuICAgICAgLy8gVE9ETzogcmV1c2UgdGhlIHN0b3JhZ2UgYnVmZmVycyBpbiBub24tZGVmYXVsdCBtb2RlLlxuICAgICAgbGV0IGNhcHR1cmVkQnVmZmVycyA9IHRoaXMuY2FwdHVyZWRQZW5kaW5nQnVmZmVycy5nZXQodGhpcy5iYWNrZW5kLmN1cnJlbnRTZXNzaW9uSWQhKTtcbiAgICAgIGlmICghY2FwdHVyZWRCdWZmZXJzKSB7XG4gICAgICAgIGNhcHR1cmVkQnVmZmVycyA9IFtdO1xuICAgICAgICB0aGlzLmNhcHR1cmVkUGVuZGluZ0J1ZmZlcnMuc2V0KHRoaXMuYmFja2VuZC5jdXJyZW50U2Vzc2lvbklkISwgY2FwdHVyZWRCdWZmZXJzKTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgYnVmZmVyIG9mIHRoaXMuYnVmZmVyc1BlbmRpbmcpIHtcbiAgICAgICAgY2FwdHVyZWRCdWZmZXJzLnB1c2goYnVmZmVyKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuYnVmZmVyc1BlbmRpbmcgPSBbXTtcbiAgICB9XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMuZnJlZUJ1ZmZlcnMuZm9yRWFjaCgoYnVmZmVycykgPT4ge1xuICAgICAgYnVmZmVycy5mb3JFYWNoKChidWZmZXIpID0+IHtcbiAgICAgICAgYnVmZmVyLmRlc3Ryb3koKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIHRoaXMuZnJlZVVuaWZvcm1CdWZmZXJzLmZvckVhY2goKGJ1ZmZlcnMpID0+IHtcbiAgICAgIGJ1ZmZlcnMuZm9yRWFjaCgoYnVmZmVyKSA9PiB7XG4gICAgICAgIGJ1ZmZlci5kZXN0cm95KCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRoaXMuc3RvcmFnZUNhY2hlLmZvckVhY2goKHN0b3JhZ2UpID0+IHtcbiAgICAgIHN0b3JhZ2UuZ3B1RGF0YS5idWZmZXIuZGVzdHJveSgpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5jYXB0dXJlZFBlbmRpbmdCdWZmZXJzLmZvckVhY2goKGJ1ZmZlcnMpID0+IHtcbiAgICAgIGJ1ZmZlcnMuZm9yRWFjaCgoYnVmZmVyKSA9PiB7XG4gICAgICAgIGJ1ZmZlci5kZXN0cm95KCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICB0aGlzLnN0b3JhZ2VDYWNoZSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmZyZWVCdWZmZXJzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZnJlZVVuaWZvcm1CdWZmZXJzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuY2FwdHVyZWRQZW5kaW5nQnVmZmVycyA9IG5ldyBNYXAoKTtcbiAgfVxuXG4gIG9uQ3JlYXRlU2Vzc2lvbigpIHtcbiAgICB0aGlzLnNlc3Npb25Db3VudCArPSAxO1xuICB9XG5cbiAgb25SZWxlYXNlU2Vzc2lvbihzZXNzaW9uSWQ6IG51bWJlcikge1xuICAgIC8vIHJlbGVhc2UgdGhlIGNhcHR1cmVkIHBlbmRpbmcgYnVmZmVycy5cbiAgICBjb25zdCBwZW5kaW5nQnVmZmVycyA9IHRoaXMuY2FwdHVyZWRQZW5kaW5nQnVmZmVycy5nZXQoc2Vzc2lvbklkKTtcbiAgICBpZiAocGVuZGluZ0J1ZmZlcnMpIHtcbiAgICAgIHBlbmRpbmdCdWZmZXJzLmZvckVhY2goKGJ1ZmZlcikgPT4ge1xuICAgICAgICBidWZmZXIuZGVzdHJveSgpO1xuICAgICAgfSk7XG4gICAgICB0aGlzLmNhcHR1cmVkUGVuZGluZ0J1ZmZlcnMuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgfVxuXG4gICAgLy8gcmVsZWFzZSB0aGUgc3RvcmFnZSBjYWNoZSBpZiBubyBhY3RpdmUgc2Vzc2lvbnMuXG4gICAgdGhpcy5zZXNzaW9uQ291bnQgLT0gMTtcbiAgICBpZiAodGhpcy5zZXNzaW9uQ291bnQgPT09IDApIHtcbiAgICAgIExPR19ERUJVRygnd2FybmluZycsICgpID0+ICdbV2ViR1BVXSBDbGVhcmluZyB3ZWJncHUgYnVmZmVyIGNhY2hlJyk7XG4gICAgICB0aGlzLnN0b3JhZ2VDYWNoZS5mb3JFYWNoKChzdG9yYWdlKSA9PiB7XG4gICAgICAgIHN0b3JhZ2UuZ3B1RGF0YS5idWZmZXIuZGVzdHJveSgpO1xuICAgICAgfSk7XG4gICAgICB0aGlzLnN0b3JhZ2VDYWNoZSA9IG5ldyBNYXAoKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGNyZWF0ZUdwdURhdGFNYW5hZ2VyID0gKC4uLmFyZ3M6IENvbnN0cnVjdG9yUGFyYW1ldGVyczx0eXBlb2YgR3B1RGF0YU1hbmFnZXJJbXBsPik6IEdwdURhdGFNYW5hZ2VyID0+XG4gIG5ldyBHcHVEYXRhTWFuYWdlckltcGwoLi4uYXJncyk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmNsYXNzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleUltcGwge1xuICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSB7XG4gICAgT2JqZWN0LmFzc2lnbih0aGlzLCBhdHRyaWJ1dGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBrZXk6IHN0cmluZztcbiAgcHVibGljIGdldCBjYWNoZUtleSgpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5rZXkpIHtcbiAgICAgIHRoaXMua2V5ID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcylcbiAgICAgICAgLnNvcnQoKVxuICAgICAgICAubWFwKChuYW1lKSA9PiBgJHsodGhpcyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilbbmFtZV19YClcbiAgICAgICAgLmpvaW4oJzsnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMua2V5O1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgY2FjaGVLZXk6IHN0cmluZztcbn1cblxuLyoqXG4gKiBjcmVhdGUgYSBuZXcgb2JqZWN0IGZyb20gdGhlIGdpdmVuIGF0dHJpYnV0ZSwgYW5kIGFkZCBhIGNhY2hlS2V5IHByb3BlcnR5IHRvIGl0XG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgPSA8VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+PihcbiAgYXR0cmlidXRlOiBULFxuKTogVCAmIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSA9PiBuZXcgQXR0cmlidXRlV2l0aENhY2hlS2V5SW1wbChhdHRyaWJ1dGUpIGFzIHVua25vd24gYXMgVCAmIEF0dHJpYnV0ZVdpdGhDYWNoZUtleTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IFByb2dyYW1Vbmlmb3JtLCBQcm9ncmFtVW5pZm9ybVZhcmlhYmxlSW5mbyB9IGZyb20gJy4uL3R5cGVzJztcblxuLyoqXG4gKiBjb25zdGFudCB2YWx1ZSBmb3IgYSB3b3JrZ3JvdXAgc2l6ZS5cbiAqXG4gKiBXZSBkZWZpbml0ZWx5IGNhbiBkbyBmdXJ0aGVyIG9wdGltaXphdGlvbiBpbiBmdXR1cmUsIGJ1dCBmb3Igbm93IHdlIHVzZSA2NC5cbiAqXG4gKiBydWxlIG9mIHRodW1iOiBVc2UgW2Egd29ya2dyb3VwIHNpemUgb2ZdIDY0IHVubGVzcyB5b3Uga25vdyB3aGF0IEdQVSB5b3UgYXJlIHRhcmdldGluZyBvciB0aGF0IHlvdXIgd29ya2xvYWRcbiAqICAgICAgICAgICAgICAgIG5lZWRzIHNvbWV0aGluZyBkaWZmZXJlbnQuXG4gKlxuICogZnJvbTogaHR0cHM6Ly9zdXJtYS5kZXYvdGhpbmdzL3dlYmdwdS9cbiAqKi9cbmV4cG9ydCBjb25zdCBXT1JLR1JPVVBfU0laRSA9IDY0O1xuXG5pbnRlcmZhY2UgSW5kaWNlc0hlbHBlclR5cGVzIHtcbiAgLyoqXG4gICAqIFdHU0wgdHlwZSBvZiBpbmRpY2VzIGV4cHJlc3Npb25cbiAgICovXG4gIHJlYWRvbmx5IGluZGljZXM6IHN0cmluZztcblxuICAvKipcbiAgICogV0dTTCB0eXBlIG9mIGEgdmFsdWVcbiAgICovXG4gIHJlYWRvbmx5IHZhbHVlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdHU0wgdHlwZSBvZiBzdG9yYWdlIHR5cGUgcmVwcmVzZW50aW5nIGEgdmFsdWVcbiAgICpcbiAgICogVGhpcyBpcyB1c3VhbGx5IHRoZSBzYW1lIHRvIGB2YWx1ZWAsIGJ1dCBmb3Igc29tZSB0eXBlIChlZy4gYm9vbCksIHdlIG5lZWQgdG8gdXNlIGB1MzJgIGFzIHN0b3JhZ2UgdHlwZSBmb3JcbiAgICogdmFsdWUgdHlwZSBgdmVjNDxib29sPmBcbiAgICovXG4gIHJlYWRvbmx5IHN0b3JhZ2U6IHN0cmluZztcblxuICAvKipcbiAgICogdGVuc29yIHR5cGUgYXMgcmVwcmVzZW50ZWQgaW4gVGVuc29yVmlld1xuICAgKi9cbiAgcmVhZG9ubHkgdGVuc29yOiBudW1iZXI7XG59XG5cbi8qKlxuICogQSBoZWxwZXIgY2xhc3MgZm9yIGdlbmVyYXRpbmcgV0dTTCBjb2RlIGZvciBtYW5pcHVsYXRpbmcgaW5kaWNlcyBhbmQgZGF0YSBmb3IgYSBzaGFkZXIncyBpbnB1dCBvciBvdXRwdXQuXG4gKlxuICogVGhpcyBjbGFzcyBpcyBkZXNpZ25lZCB0byBvZmZlciBhIHVuaWZpZWQgd2F5IHRvIGdlbmVyYXRlIFdHU0wgY29kZSBmb3IgbWFuaXB1bGF0aW5nIGluZGljZXMgYW5kIGRhdGEgZm9yIGEgc2hhZGVyJ3NcbiAqIGlucHV0IG9yIG91dHB1dC5cbiAqXG4gKiBUaGUgZm9sbG93aW5nIGlzIGEgbGlzdCBvZiB0ZXJtaW5vbG9naWVzIHVzZWQgaW4gdGhpcyBjbGFzczpcbiAqIC0gYG9mZnNldGA6IGEgdWludDMyIHZhbHVlIHJlcHJlc2VudGluZyB0aGUgb2Zmc2V0IG9mIGFuIGVsZW1lbnQgaW4gdGhlIGRhdGEgYnVmZmVyLlxuICogLSBgaW5kaWNlc2A6IGFuIGFic3RyYWN0aW9uIG9mIGEgbXVsdGktZGltZW5zaW9uYWwgYXJyYXkncyBpbmRpY2VzIHJlcHJlc2VudGluZyB0aGUgZGF0YSdzIGluZGV4IG9uIGVhY2ggZGltZW5zaW9uLlxuICogLSBgdmFsdWVgOiBhIHZhbHVlIG9mIGEgZGF0YSBlbGVtZW50LlxuICpcbiAqIFVzZXJzIGFyZSBleHBlY3RlZCB0byBjcmVhdGUgYW4gaW5zdGFuY2Ugb2YgdGhpcyBjbGFzcyBmb3IgZWFjaCBzaGFkZXIncyBpbnB1dCBvciBvdXRwdXQsIGFuZCB1c2UgdGhlIGluc3RhbmNlIHRvXG4gKiBnZW5lcmF0ZSBXR1NMIGNvZGUgZm9yIG1hbmlwdWxhdGluZyBpbmRpY2VzIGFuZCBkYXRhLiBUaGUgZm9sbG93aW5nIDIgZXhwb3J0ZWQgZnVuY3Rpb25zIGFyZSBmb3IgdXNlcnMgdG8gY2FsbCB0b1xuICogY3JlYXRlIGFuIGluc3RhbmNlIG9mIGFuIGluZGljZXMgaGVscGVyOlxuICogLSBgaW5wdXRWYXJpYWJsZSgpYDogY3JlYXRlIGFuIGluZGljZXMgaGVscGVyIGluc3RhbmNlIGZvciBhbiBpbnB1dC5cbiAqIC0gYG91dHB1dFZhcmlhYmxlKClgOiBjcmVhdGUgYW4gaW5kaWNlcyBoZWxwZXIgaW5zdGFuY2UgZm9yIGFuIG91dHB1dC5cbiAqIC0gYGludGVybmFsVmFyaWFibGUoKWA6IGNyZWF0ZSBhbiBpbmRpY2VzIGhlbHBlciBpbnN0YW5jZSBmb3IgYW4gaW50ZXJuYWwgdmFyaWFibGUuXG4gKlxuICogQW4gaW5kaWNlcyBoZWxwZXIgaW5zdGFuY2UgY29udGFpbnMgaGVscGVyIGZ1bmN0aW9ucyBmb3IgdGhlIGZvbGxvd2luZyBvcGVyYXRpb25zOlxuICogLSBhY2Nlc3MgcmVhZG9ubHkgYmFzaWMgaW5mb3JtYXRpb24sIGluY2x1ZGluZzogYG5hbWVgKHRoZSBuYW1lIG9mIHRoZSBpbnB1dCBvciBvdXRwdXQpLCBgdXNhZ2VgKHdoZXRoZXIgaXQncyBhblxuICogaW5wdXQsIGFuIG91dHB1dCBvciBhbiBpbnRlcm5hbCB2YXJpYWJsZSkgYW5kIGBzaGFwZWAodGhlIHBhc3NlZCBpbiBzaGFwZSkuXG4gKiAtIGB0eXBlYDogYWNjZXNzIHJlYWRvbmx5IHR5cGUgaW5mb3JtYXRpb24sIGluY2x1ZGluZzogYGluZGljZXNgKHRoZSB0eXBlIG9mIGluZGljZXMpLCBgdmFsdWVgKHRoZSB0eXBlIG9mIHZhbHVlIGF0XG4gKiBydW50aW1lKSwgYHN0b3JhZ2VgKHRoZSB0eXBlIG9mIHZhbHVlIGF0IHN0b3JhZ2UpIGFuZCBgdGVuc29yYCh0aGUgdGVuc29yIHR5cGUgYXMgcmVwcmVzZW50ZWQgaW4gVGVuc29yVmlldykuXG4gKiAtIGdlbmVyYXRlIFdHU0wgY29kZSBmb3IgZ2V0dGluZyBpbmRpY2VzIGZyb20gb2Zmc2V0LiBVc2UgYG9mZnNldFRvSW5kaWNlcygpYCBmb3IgV0dTTCBjb2RlIHNuaXBwZXQgdG8gY2FsY3VsYXRlXG4gKiBpbmRpY2VzIGZyb20gb2Zmc2V0LCBhbmQgdXNlIGBpbmRpY2VzVG9PZmZzZXQoKWAgZm9yIFdHU0wgY29kZSBzbmlwcGV0IHRvIGNhbGN1bGF0ZSBvZmZzZXQgZnJvbSBpbmRpY2VzLlxuICogLSB0byBtYW5pcHVsYXRlIGFuIGluc3RhbmNlIG9mIGluZGljZXMsIHVzZSBgc2V0SW5kaWNlcygpYCBhbmQgYGdldEluZGljZXMoKWAgdG8gc2V0IGFuZCBnZXQgdGhlIGluZGljZXMgb24gYW5cbiAqIGluZGljZXMgdmFyaWFibGUuXG4gKiAtIHRvIG1hbmlwdWxhdGUgZGF0YSwgdXNlIGBzZXQoKWAvYGdldCgpYCB0byBhY2Nlc3MgZGF0YSBhdCB0aGUgZ2l2ZW4gaW5kaWNlcyBmcm9tIHBhcmFtZXRlciBsaXN0LCB1c2VcbiAqIGBzZXRCeUluZGljZXMoKWAvYGdldEJ5SW5kaWNlcygpYCB0byBhY2Nlc3MgZGF0YSBhdCB0aGUgZ2l2ZW4gaW5kaWNlcyBmcm9tIGFuIGluZGljZXMgdmFyaWFibGUsIGFuZCB1c2VcbiAqIGBzZXRCeU9mZnNldCgpYC9gZ2V0QnlPZmZzZXQoKWAgdG8gYWNjZXNzIGRhdGEgYXQgdGhlIGdpdmVuIG9mZnNldC5cbiAqIC0gYGltcGxgOiBnZXQgV0dTTCBjb2RlIG9mIGZ1bmN0aW9uIGltcGxlbWVudGF0aW9uIGZvciB0aGUgdXRpbCBmdW5jdGlvbnMgbWVudGlvbmVkIGFib3ZlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEluZGljZXNIZWxwZXIge1xuICAvKipcbiAgICogZ2V0IFdHU0wgY29kZSBvZiBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvbiBmb3IgdGhlIHV0aWwgZnVuY3Rpb25zLlxuICAgKlxuICAgKi9cbiAgcmVhZG9ubHkgaW1wbDogKCkgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBnZXQgdHlwZSBpbmZvXG4gICAqL1xuICByZWFkb25seSB0eXBlOiBJbmRpY2VzSGVscGVyVHlwZXM7XG5cbiAgLyoqXG4gICAqIFdHU0wgY29kZSBvZiBhIGV4cHJlc3Npb24gZm9yIGdldHRpbmcgaW5kaWNlcyBmcm9tIG9mZnNldC5cbiAgICpcbiAgICogQHBhcmFtIHZhck9mZnNldCAtIGEgdTMyIGV4cHJlc3Npb24gcmVwcmVzZW50aW5nIHRoZSBvZmZzZXQuXG4gICAqXG4gICAqIEByZXR1cm5zIGFuIGB0eXBlLmluZGljZXNgIGV4cHJlc3Npb25cbiAgICovXG4gIHJlYWRvbmx5IG9mZnNldFRvSW5kaWNlczogKHZhck9mZnNldDogc3RyaW5nKSA9PiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdHU0wgY29kZSBvZiBhbiBgdTMyYCBleHByZXNzaW9uIGZvciBnZXR0aW5nIG9mZnNldCBmcm9tIGluZGljZXMuXG4gICAqXG4gICAqIEBwYXJhbSB2YXJJbmRpY2VzIC0gYSBgdHlwZS5pbmRpY2VzYCBleHByZXNzaW9uIHJlcHJlc2VudGluZyB0aGUgaW5kaWNlcy5cbiAgICpcbiAgICogQHJldHVybnMgYW4gYHUzMmAgZXhwcmVzc2lvblxuICAgKi9cbiAgcmVhZG9ubHkgaW5kaWNlc1RvT2Zmc2V0OiAodmFySW5kaWNlczogc3RyaW5nKSA9PiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdHU0wgY29kZSBvZiBhbiBgdTMyYCBleHByZXNzaW9uIGZvciBnZXR0aW5nIG9yaWdpbmFsIG9mZnNldCBmcm9tIGJyb2FkY2FzdGVkIGluZGljZXMuXG4gICAqXG4gICAqIEBwYXJhbSB2YXJJbmRpY2VzIC0gYSBgdHlwZS5pbmRpY2VzYCBleHByZXNzaW9uIHJlcHJlc2VudGluZyB0aGUgb3V0cHV0IGluZGljZXMuXG4gICAqIEBwYXJhbSBvdXRwdXQgLSBvdXRwdXQgSW5kaWNlc0hlbHBlci5cbiAgICpcbiAgICogQHJldHVybnMgYW4gYHUzMmAgZXhwcmVzc2lvblxuICAgKi9cbiAgcmVhZG9ubHkgYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQ6ICh2YXJJbmRpY2VzOiBzdHJpbmcsIG91dHB1dDogSW5kaWNlc0hlbHBlcikgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXR1NMIGNvZGUgb2YgZ2VuZXJhdGluZyBhbiBpbmRpY2VzIGxpdGVyYWxcbiAgICpcbiAgICogQHBhcmFtIGluaXQgLSBpbml0aWFsIHZhbHVlLlxuICAgKi9cbiAgcmVhZG9ubHkgaW5kaWNlczogKC4uLmluaXQ6IFJlYWRvbmx5QXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXR1NMIGNvZGUgb2YgYSBzdGF0ZW1lbnQgZm9yIHNldHRpbmcgaW5kaWNlcy5cbiAgICpcbiAgICogQHBhcmFtIHZhckluZGljZXMgLSBhIHZhcmlhYmxlIG5hbWUgZm9yIHRoZSBpbmRpY2VzLlxuICAgKiBAcGFyYW0gaWR4IC0gdGhlIGluZGV4IG9mIHRoZSBpbmRpY2VzIHRvIHNldC4gY2FuIGJlIGEgbnVtYmVyIG9yIGEgc3RyaW5nIChXR1NMIGB1MzJgIGV4cHJlc3Npb24pLlxuICAgKiBAcGFyYW0gdmFsdWUgLSB0aGUgdmFsdWUgdG8gc2V0LiBjYW4gYmUgYSBudW1iZXIgb3IgYSBzdHJpbmcgKFdHU0wgYHUzMmAgZXhwcmVzc2lvbikuXG4gICAqXG4gICAqIEByZXR1cm5zIGEgV0dTTCBzdGF0ZW1lbnRcbiAgICovXG4gIHJlYWRvbmx5IGluZGljZXNTZXQ6ICh2YXJJbmRpY2VzOiBzdHJpbmcsIGlkeDogbnVtYmVyIHwgc3RyaW5nLCB2YWx1ZTogbnVtYmVyIHwgc3RyaW5nKSA9PiB2b2lkO1xuXG4gIC8qKlxuICAgKiBXR1NMIGNvZGUgb2YgYW4gYHUzMmAgZXhwcmVzc2lvbiBmb3IgZ2V0dGluZyBpbmRpY2VzLlxuICAgKlxuICAgKiBAcGFyYW0gdmFySW5kaWNlcyAtIGEgdmFyaWFibGUgbmFtZSBmb3IgdGhlIGluZGljZXMuXG4gICAqIEBwYXJhbSBpZHggLSB0aGUgaW5kZXggb2YgdGhlIGluZGljZXMgdG8gZ2V0LiBjYW4gYmUgYSBudW1iZXIgb3IgYSBzdHJpbmcgKFdHU0wgYHUzMmAgZXhwcmVzc2lvbikuXG4gICAqXG4gICAqIEByZXR1cm5zIGFuIGB1MzJgIGV4cHJlc3Npb25cbiAgICovXG4gIHJlYWRvbmx5IGluZGljZXNHZXQ6ICh2YXJJbmRpY2VzOiBzdHJpbmcsIGlkeDogbnVtYmVyIHwgc3RyaW5nKSA9PiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdHU0wgY29kZSBmb3IgYSBzdGF0ZW1lbnQgZm9yIHNldHRpbmcgZGF0YSBhdCB0aGUgZ2l2ZW4gaW5kaWNlcy5cbiAgICpcbiAgICogQHBhcmFtIGluZGljZXNBbmRWYWx1ZSAtIGFuIGFycmF5IG9mIG51bWJlcnMgb3Igc3RyaW5ncyAoV0dTTCBgdTMyYCBleHByZXNzaW9uKSByZXByZXNlbnRpbmcgdGhlIGluZGljZXMsIGZvbGxvd2VkXG4gICAqICAgICBieSB0aGUgdmFsdWUgdG8gc2V0LiBUaGlzIGFycmF5IHNob3VsZCBoYXZlIGV4YWN0bHkgYHNoYXBlLmxlbmd0aCArIDFgIGVsZW1lbnRzLlxuICAgKi9cbiAgcmVhZG9ubHkgc2V0OiAoLi4uaW5kaWNlc0FuZFZhbHVlOiBSZWFkb25seUFycmF5PG51bWJlciB8IHN0cmluZz4pID0+IHN0cmluZztcblxuICAvKipcbiAgICogV0dTTCBjb2RlIGZvciBhIHN0YXRlbWVudCBmb3Igc2V0dGluZyBkYXRhIGF0IHRoZSBnaXZlbiBpbmRpY2VzIHZhcmlhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gdmFySW5kaWNlcyAtIGEgdmFyaWFibGUgbmFtZSBmb3IgdGhlIGluZGljZXMuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIHRoZSB2YWx1ZSB0byBzZXQuIHNob3VsZCBiZSBhIFdHU0wgZXhwcmVzc2lvbi5cbiAgICovXG4gIHJlYWRvbmx5IHNldEJ5SW5kaWNlczogKHZhckluZGljZXM6IHN0cmluZywgdmFsdWU6IHN0cmluZykgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXR1NMIGNvZGUgZm9yIGEgc3RhdGVtZW50IGZvciBzZXR0aW5nIGRhdGEgYXQgdGhlIGdpdmVuIG9mZnNldC5cbiAgICpcbiAgICogQHBhcmFtIG9mZnNldCAtIGEgbnVtYmVyIG9yIGEgc3RyaW5nIChXR1NMIGB1MzJgIGV4cHJlc3Npb24pIHJlcHJlc2VudGluZyB0aGUgb2Zmc2V0LlxuICAgKiBAcGFyYW0gdmFsdWUgLSB0aGUgdmFsdWUgdG8gc2V0LiBzaG91bGQgYmUgYSBXR1NMIGV4cHJlc3Npb24uXG4gICAqL1xuICByZWFkb25seSBzZXRCeU9mZnNldDogKG9mZnNldDogbnVtYmVyIHwgc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSA9PiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdHU0wgY29kZSBmb3IgYW4gZXhwcmVzc2lvbiBmb3IgZ2V0dGluZyBkYXRhIGF0IHRoZSBnaXZlbiBpbmRpY2VzLlxuICAgKlxuICAgKiBAcGFyYW0gaW5kaWNlcyAtIGFuIGFycmF5IG9mIG51bWJlcnMgb3Igc3RyaW5ncyAoV0dTTCBgdTMyYCBleHByZXNzaW9uKSByZXByZXNlbnRpbmcgdGhlIGluZGljZXMuXG4gICAqL1xuICByZWFkb25seSBnZXQ6ICguLi5pbmRpY2VzOiBSZWFkb25seUFycmF5PG51bWJlciB8IHN0cmluZz4pID0+IHN0cmluZztcblxuICAvKipcbiAgICogV0dTTCBjb2RlIGZvciBhbiBleHByZXNzaW9uIGZvciBnZXR0aW5nIGRhdGEgYXQgdGhlIGdpdmVuIGluZGljZXMgdmFyaWFibGUuXG4gICAqXG4gICAqIEBwYXJhbSB2YXJJbmRpY2VzIC0gYSB2YXJpYWJsZSBuYW1lIGZvciB0aGUgaW5kaWNlcy5cbiAgICovXG4gIHJlYWRvbmx5IGdldEJ5SW5kaWNlczogKHZhckluZGljZXM6IHN0cmluZykgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXR1NMIGNvZGUgZm9yIGFuIGV4cHJlc3Npb24gZm9yIGdldHRpbmcgZGF0YSBhdCB0aGUgZ2l2ZW4gb2Zmc2V0LlxuICAgKlxuICAgKiBAcGFyYW0gb2Zmc2V0IC0gYSBudW1iZXIgb3IgYSBzdHJpbmcgKFdHU0wgYHUzMmAgZXhwcmVzc2lvbikgcmVwcmVzZW50aW5nIHRoZSBvZmZzZXQuXG4gICAqL1xuICByZWFkb25seSBnZXRCeU9mZnNldDogKG9mZnNldDogbnVtYmVyIHwgc3RyaW5nKSA9PiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIG5hbWUgb2YgdGhlIGRhdGEgdmFyaWFibGVcbiAgICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogd2hldGhlciB0aGUgaGVscGVyIGlzIGZvciBhbiBpbnB1dCwgYW4gb3V0cHV0IG9yIGFuIGludGVybmFsIHZhcmlhYmxlLlxuICAgKi9cbiAgcmVhZG9ubHkgdXNhZ2U6ICdpbnB1dCcgfCAnb3V0cHV0JyB8ICdhdG9taWNPdXRwdXQnIHwgJ2ludGVybmFsJztcblxuICAvKipcbiAgICogdGhlIHJhbmsgb2YgdGhlIGlucHV0IG9yIG91dHB1dC5cbiAgICovXG4gIHJlYWRvbmx5IHJhbms6IG51bWJlcjtcblxuICAvKipcbiAgICogYSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSB2YXJpYWJsZSBuYW1lIGZvciB0aGUgc2hhcGUgb2YgdGhlIGlucHV0IG9yIG91dHB1dC5cbiAgICovXG4gIHJlYWRvbmx5IHNoYXBlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIGEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgdmFyaWFibGUgbmFtZSBmb3IgdGhlIHN0cmlkZXMgb2YgdGhlIGlucHV0IG9yIG91dHB1dC5cbiAgICovXG4gIHJlYWRvbmx5IHN0cmlkZXM6IHN0cmluZztcbn1cblxuY29uc3QgZ2V0V2dzbE1hcHBlZFR5cGUgPSAodHlwZTogbnVtYmVyLCBjb21wb25lbnRzOiAxIHwgMiB8IDMgfCA0KTogc3RyaW5nIHwgW3N0cmluZywgc3RyaW5nXSA9PiB7XG4gIGlmIChjb21wb25lbnRzID09PSAzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd2ZWMzIGhhcyBzYW1lIGFsaWdubWVudCBhcyB2ZWM0LCB1c2UgdmVjNCBpbnN0ZWFkJyk7XG4gIH1cblxuICAvLyByZXR1cm4gdHlwZSBpcyBbIHN0b3JhZ2UgdHlwZSwgcnVudGltZSB0eXBlIF0gb3IgYSBzaW5nbGUgc3RyaW5nIGZvciBib3RoXG4gIHN3aXRjaCAoTnVtYmVyKHR5cGUpKSB7XG4gICAgY2FzZSBEYXRhVHlwZS5mbG9hdDE2OlxuICAgICAgcmV0dXJuIGNvbXBvbmVudHMgPiAxID8gYHZlYyR7Y29tcG9uZW50c308ZjE2PmAgOiAnZjE2JztcbiAgICBjYXNlIERhdGFUeXBlLmZsb2F0OlxuICAgICAgcmV0dXJuIGNvbXBvbmVudHMgPiAxID8gYHZlYyR7Y29tcG9uZW50c308ZjMyPmAgOiAnZjMyJztcbiAgICBjYXNlIERhdGFUeXBlLmludDMyOlxuICAgICAgcmV0dXJuIGNvbXBvbmVudHMgPiAxID8gYHZlYyR7Y29tcG9uZW50c308aTMyPmAgOiAnaTMyJztcbiAgICBjYXNlIERhdGFUeXBlLnVpbnQzMjpcbiAgICAgIHJldHVybiBjb21wb25lbnRzID4gMSA/IGB2ZWMke2NvbXBvbmVudHN9PHUzMj5gIDogJ3UzMic7XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQ2NDpcbiAgICAgIGlmIChjb21wb25lbnRzID4gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2N1cnJlbnRseSBub3Qgc3VwcG9ydGVkIHZlY1ggb2YgdWludDY0IHlldCcpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFsndmVjMjx1MzI+JywgJ2kzMiddO1xuICAgIGNhc2UgRGF0YVR5cGUudWludDY0OlxuICAgICAgaWYgKGNvbXBvbmVudHMgPiAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignY3VycmVudGx5IG5vdCBzdXBwb3J0ZWQgdmVjWCBvZiB1aW50NjQgeWV0Jyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gWyd2ZWMyPHUzMj4nLCAndTMyJ107XG4gICAgY2FzZSBEYXRhVHlwZS5ib29sOlxuICAgICAgaWYgKGNvbXBvbmVudHMgIT09IDQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdib29sIG11c3QgYmUgdmVjNCcpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFsndTMyJywgJ3ZlYzQ8Ym9vbD4nXTtcbiAgICBjYXNlIERhdGFUeXBlLmludDQ6XG4gICAgICByZXR1cm4gJ2kzMic7XG4gICAgY2FzZSBEYXRhVHlwZS51aW50NDpcbiAgICAgIHJldHVybiAndTMyJztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGRhdGEgdHlwZTogJHt0eXBlfWApO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlID0gKHR5cGU6IERhdGFUeXBlLCBjb21wb25lbnRzOiAxIHwgMiB8IDMgfCA0ID0gMSkgPT4ge1xuICBjb25zdCBtYXBwZWRUeXBlID0gZ2V0V2dzbE1hcHBlZFR5cGUodHlwZSwgY29tcG9uZW50cyk7XG4gIHJldHVybiB0eXBlb2YgbWFwcGVkVHlwZSA9PT0gJ3N0cmluZycgPyBtYXBwZWRUeXBlIDogbWFwcGVkVHlwZVswXTtcbn07XG5cbmV4cG9ydCBjb25zdCB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlID0gKHR5cGU6IERhdGFUeXBlLCBjb21wb25lbnRzOiAxIHwgMiB8IDMgfCA0ID0gMSkgPT4ge1xuICBjb25zdCBtYXBwZWRUeXBlID0gZ2V0V2dzbE1hcHBlZFR5cGUodHlwZSwgY29tcG9uZW50cyk7XG4gIHJldHVybiB0eXBlb2YgbWFwcGVkVHlwZSA9PT0gJ3N0cmluZycgPyBtYXBwZWRUeXBlIDogbWFwcGVkVHlwZVsxXTtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyA9ICguLi5kaW1zOiBSZWFkb25seUFycmF5PHJlYWRvbmx5IG51bWJlcltdPik6IFByb2dyYW1Vbmlmb3JtW10gPT4ge1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXTtcbiAgZGltcy5mb3JFYWNoKChkaW0pID0+IHtcbiAgICBpZiAoZGltLmxlbmd0aCAhPT0gMCkge1xuICAgICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goXG4gICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBkaW0gfSxcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IFNoYXBlVXRpbC5jb21wdXRlU3RyaWRlcyhkaW0pIH0sXG4gICAgICApO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBwcm9ncmFtVW5pZm9ybXM7XG59O1xuXG4vKipcbiAqIEEgaGVscGVyIGZ1bmN0aW9uIHRvIGdldCBtYXhpbXVtIHZlY3RvciBzaXplIGZvciBzcGVjaWZpZWQgZGF0YSBsZW5ndGhcbiAqIEBwYXJhbSBzaXplXG4gKi9cbmV4cG9ydCBjb25zdCBnZXRNYXhDb21wb25lbnRzID0gKHNpemU6IG51bWJlcikgPT4ge1xuICAvLyB3ZSBjYW5ub3QgdXNlIHZlYzMgdHlwZSBzaW5jZSBpdCBoYXMgYWxpZ25tZW50IG9mIDE2IGJ5dGVzXG4gIGlmIChzaXplICUgNCA9PT0gMCkge1xuICAgIHJldHVybiA0O1xuICB9IGVsc2UgaWYgKHNpemUgJSAyID09PSAwKSB7XG4gICAgcmV0dXJuIDI7XG4gIH1cblxuICByZXR1cm4gMTtcbn07XG5cbi8qKlxuICogQSBoZWxwZXIgZnVuY3Rpb24gdGhhdCBpbml0aWFsaXplcyB2YXJpYWJsZSBhcyBhIHNjYWxhciBvciB2ZWN0b3IuIGUuZy4gZjMyKDApIG9yIHZlYzRmKDAsMCwwLDApXG4gKiBAcGFyYW0gZGF0YVR5cGVcbiAqIEBwYXJhbSBjb21wb25lbnRzXG4gKiBAcGFyYW0gdmFsdWVcbiAqL1xuZXhwb3J0IGNvbnN0IGZpbGxWZWN0b3IgPSAoZGF0YVR5cGUgPSAnZjMyJywgY29tcG9uZW50cz86IG51bWJlciwgdmFsdWUgPSAnMCcpID0+IHtcbiAgaWYgKCFjb21wb25lbnRzIHx8IGNvbXBvbmVudHMgPT09IDEpIHtcbiAgICByZXR1cm4gYCR7ZGF0YVR5cGV9KCR7dmFsdWV9KWA7XG4gIH1cblxuICByZXR1cm4gYHZlYyR7Y29tcG9uZW50c308JHtkYXRhVHlwZX0+KCR7dmFsdWV9KWA7XG59O1xuXG4vKipcbiAqIEEgaGVscGVyIGZ1bmN0aW9uIHRoYXQgY2FzdHMgdmFsdWUgb3IgdmVjdG9yIHRvIGYzMlxuICogQHBhcmFtIGRhdGFUeXBlXG4gKiBAcGFyYW0gY29tcG9uZW50c1xuICogQHBhcmFtIHZhbHVlXG4gKi9cbmV4cG9ydCBjb25zdCBjYXN0VG9GMzIgPSAoZGF0YVR5cGU6IHN0cmluZywgY29tcG9uZW50czogbnVtYmVyLCB2YWx1ZTogc3RyaW5nKSA9PiB7XG4gIGlmIChkYXRhVHlwZSA9PT0gJ2YzMicpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbiAgaWYgKGNvbXBvbmVudHMgPT09IDEpIHtcbiAgICByZXR1cm4gYGYzMigke3ZhbHVlfSlgO1xuICB9XG5cbiAgcmV0dXJuIGB2ZWMke2NvbXBvbmVudHN9PGYzMj4oJHt2YWx1ZX0pYDtcbn07XG5cbi8qKlxuICogQSBoZWxwZXIgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHNjYWxhciBvciBzdW1zIGFsbCBjb21wb25lbnRzIG9mIGEgdmVjdG9yXG4gKiBAcGFyYW0gbmFtZVxuICogQHBhcmFtIGNvbXBvbmVudHNcbiAqL1xuZXhwb3J0IGNvbnN0IHN1bVZlY3RvciA9IChuYW1lOiBzdHJpbmcsIGNvbXBvbmVudHM6IG51bWJlcikgPT4ge1xuICBpZiAoY29tcG9uZW50cyA9PT0gNCkge1xuICAgIHJldHVybiBgKCR7bmFtZX0ueCArICR7bmFtZX0ueSArICR7bmFtZX0ueiArICR7bmFtZX0udylgO1xuICB9IGVsc2UgaWYgKGNvbXBvbmVudHMgPT09IDIpIHtcbiAgICByZXR1cm4gYCgke25hbWV9LnggKyAke25hbWV9LnkpYDtcbiAgfSBlbHNlIGlmIChjb21wb25lbnRzID09PSAzKSB7XG4gICAgcmV0dXJuIGAoJHtuYW1lfS54ICsgJHtuYW1lfS55ICsgJHtuYW1lfS56KWA7XG4gIH1cblxuICByZXR1cm4gbmFtZTtcbn07XG5cbi8qKlxuICogQSBoZWxwZXIgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHZhcmlhYmxlIGVsZW1lbnQgYXQgaW5kZXguXG4gKiBAcGFyYW0gbmFtZSAtIHRoZSBuYW1lIG9mIHZhcmlhYmxlLlxuICogQHBhcmFtIGluZGV4IC0gdGhlIGluZGV4IG9mIHZhcmlhYmxlIGVsZW1lbnQuXG4gKiBAcGFyYW0gbGVuZ3RoIC0gdGhlIGxlbmd0aCBvZiB2YXJpYWJsZS5cbiAqIEBwYXJhbSB0eXBlIC0gdGhlIHR5cGUgb2YgdmFyaWFibGUsIG9wdGlvbmFsLlxuICovXG5leHBvcnQgY29uc3QgZ2V0RWxlbWVudEF0ID0gKFxuICBuYW1lOiBzdHJpbmcsXG4gIGluZGV4OiBudW1iZXIgfCBzdHJpbmcsXG4gIGxlbmd0aDogbnVtYmVyLFxuICB0eXBlPzogVW5pZm9ybURhdGFFbGVtZW50VHlwZSxcbik6IHN0cmluZyA9PiB7XG4gIGlmIChuYW1lLnN0YXJ0c1dpdGgoJ3VuaWZvcm1zLicpICYmIGxlbmd0aCA+IDQpIHtcbiAgICBpZiAodHlwZW9mIGluZGV4ID09PSAnc3RyaW5nJykge1xuICAgICAgaWYgKHR5cGUgPT09ICdmMTYnKSB7XG4gICAgICAgIHJldHVybiBgJHtuYW1lfVsoJHtpbmRleH0pIC8gOF1bKCR7aW5kZXh9KSAlIDggLyA0XVsoJHtpbmRleH0pICUgOCAlIDRdYDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBgJHtuYW1lfVsoJHtpbmRleH0pIC8gNF1bKCR7aW5kZXh9KSAlIDRdYDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHR5cGUgPT09ICdmMTYnKSB7XG4gICAgICAgIHJldHVybiBgJHtuYW1lfVske01hdGguZmxvb3IoaW5kZXggLyA4KX1dWyR7TWF0aC5mbG9vcigoaW5kZXggJSA4KSAvIDQpfV1bJHsoaW5kZXggJSA4KSAlIDR9XWA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gYCR7bmFtZX1bJHtNYXRoLmZsb29yKGluZGV4IC8gNCl9XVske2luZGV4ICUgNH1dYDtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGxlbmd0aCA+IDEgPyBgJHtuYW1lfVske2luZGV4fV1gIDogbmFtZTtcbiAgfVxufTtcblxuLyoqXG4gKiBBIGhlbHBlciBmdW5jdGlvbiB0byBnZXQgYSBJbmRpY2VzSGVscGVyIGZvciBhIGdpdmVuIGlucHV0IG9yIG91dHB1dC5cbiAqXG4gKiBAcGFyYW0gbmFtZSAtIHRoZSBuYW1lIG9mIHRoZSBpbnB1dCBvciBvdXRwdXQuXG4gKiBAcGFyYW0gdGVuc29yVHlwZSAtIHRoZSB0ZW5zb3IgdHlwZSBvZiB0aGUgaW5wdXQgb3Igb3V0cHV0LlxuICogQHBhcmFtIHNoYXBlT3JSYW5rIC0gdGhlIHRlbnNvciBzaGFwZSBvciB0aGUgcmFuayBvZiB0aGUgaW5wdXQgb3Igb3V0cHV0LlxuICogQHBhcmFtIHVzYWdlIC0gdGhlIHVzYWdlIG9mIHRoZSBpbmRpY2VzIGhlbHBlci5cbiAqIEBwYXJhbSBjb21wb25lbnRzIC0gaW5kaWNhdGVzIHRoZSBudW1iZXIgb2YgY29tcG9uZW50cyBvZiBlYWNoIGVsZW1lbnQuIDEgZm9yIHNjYWxhciwgMiBmb3IgdmVjMiwgMyBmb3IgdmVjMywgNCBmb3JcbiAqICAgIHZlYzQuXG4gKi9cbmNvbnN0IGNyZWF0ZUluZGljZXNIZWxwZXIgPSAoXG4gIG5hbWU6IHN0cmluZyxcbiAgdGVuc29yVHlwZTogbnVtYmVyLFxuICBzaGFwZU9yUmFuazogbnVtYmVyIHwgcmVhZG9ubHkgbnVtYmVyW10sXG4gIHVzYWdlOiBJbmRpY2VzSGVscGVyWyd1c2FnZSddLFxuICBjb21wb25lbnRzOiAxIHwgMiB8IDMgfCA0LFxuKTogSW5kaWNlc0hlbHBlciA9PiB7XG4gIGNvbnN0IHVzZVVuaWZvcm0gPSB0eXBlb2Ygc2hhcGVPclJhbmsgPT09ICdudW1iZXInO1xuICBjb25zdCByYW5rID0gdXNlVW5pZm9ybSA/IHNoYXBlT3JSYW5rIDogc2hhcGVPclJhbmsubGVuZ3RoO1xuICBjb25zdCByYW5rSWRlbnRpdHkgPSBbLi4ubmV3IEFycmF5KHJhbmspLmtleXMoKV07XG4gIGNvbnN0IGluZGljZXNUeXBlID0gcmFuayA8IDIgPyAndTMyJyA6IHJhbmsgPD0gNCA/IGB2ZWMke3Jhbmt9PHUzMj5gIDogYGFycmF5PHUzMiwgJHtyYW5rfT5gO1xuICBjb25zdCBtYXBwZWRUeXBlID0gZ2V0V2dzbE1hcHBlZFR5cGUodGVuc29yVHlwZSwgY29tcG9uZW50cyk7XG4gIGNvbnN0IHZhbHVlVHlwZSA9IHR5cGVvZiBtYXBwZWRUeXBlID09PSAnc3RyaW5nJyA/IG1hcHBlZFR5cGUgOiBtYXBwZWRUeXBlWzFdO1xuICBjb25zdCBzdG9yYWdlVHlwZSA9IHR5cGVvZiBtYXBwZWRUeXBlID09PSAnc3RyaW5nJyA/IG1hcHBlZFR5cGUgOiBtYXBwZWRUeXBlWzBdO1xuICBjb25zdCB0eXBlID0geyBpbmRpY2VzOiBpbmRpY2VzVHlwZSwgdmFsdWU6IHZhbHVlVHlwZSwgc3RvcmFnZTogc3RvcmFnZVR5cGUsIHRlbnNvcjogdGVuc29yVHlwZSB9O1xuXG4gIGNvbnN0IG5vcm1hbGl6ZURpbSA9IChkaW06IG51bWJlciB8IHN0cmluZyk6IHN0cmluZyA9PiAodHlwZW9mIGRpbSA9PT0gJ3N0cmluZycgPyBkaW0gOiBgJHtkaW19dWApO1xuXG4gIGNvbnN0IGltcGxlbWVudGF0aW9uVXNlZCA9IHtcbiAgICBvZmZzZXRUb0luZGljZXM6IGZhbHNlLFxuICAgIGluZGljZXNUb09mZnNldDogZmFsc2UsXG4gICAgYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQ6IGZhbHNlLFxuICAgIHNldDogZmFsc2UsXG4gICAgc2V0QnlJbmRpY2VzOiBmYWxzZSxcbiAgICBnZXQ6IGZhbHNlLFxuICAgIGdldEJ5SW5kaWNlczogZmFsc2UsXG4gIH07XG5cbiAgY29uc3QgdW5pZm9ybVByZWZpeCA9IHVzZVVuaWZvcm0gPyAndW5pZm9ybXMuJyA6ICcnO1xuICBjb25zdCBzaGFwZSA9IGAke3VuaWZvcm1QcmVmaXh9JHtuYW1lfV9zaGFwZWA7XG4gIGNvbnN0IHN0cmlkZXMgPSBgJHt1bmlmb3JtUHJlZml4fSR7bmFtZX1fc3RyaWRlc2A7XG5cbiAgbGV0IG8yaVNuaXBwZXQgPSAnJztcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCByYW5rIC0gMTsgaSsrKSB7XG4gICAgbzJpU25pcHBldCArPSBgXG4gICAgbGV0IGRpbSR7aX0gPSBjdXJyZW50IC8gJHtnZXRFbGVtZW50QXQoc3RyaWRlcywgaSwgcmFuayl9O1xuICAgIGxldCByZXN0JHtpfSA9IGN1cnJlbnQgJSAke2dldEVsZW1lbnRBdChzdHJpZGVzLCBpLCByYW5rKX07XG4gICAgaW5kaWNlc1ske2l9XSA9IGRpbSR7aX07XG4gICAgY3VycmVudCA9IHJlc3Qke2l9O1xuICAgIGA7XG4gIH1cbiAgbzJpU25pcHBldCArPSBgaW5kaWNlc1ske3JhbmsgLSAxfV0gPSBjdXJyZW50O2A7XG5cbiAgY29uc3Qgb2Zmc2V0VG9JbmRpY2VzSW1wbGVtZW50YXRpb24gPVxuICAgIHJhbmsgPCAyXG4gICAgICA/ICcnXG4gICAgICA6IGBcbiAgZm4gbzJpXyR7bmFtZX0ob2Zmc2V0OiB1MzIpIC0+ICR7dHlwZS5pbmRpY2VzfSB7XG4gICAgdmFyIGluZGljZXM6ICR7dHlwZS5pbmRpY2VzfTtcbiAgICB2YXIgY3VycmVudCA9IG9mZnNldDtcbiAgICAke28yaVNuaXBwZXR9XG4gICAgcmV0dXJuIGluZGljZXM7XG4gIH1gO1xuXG4gIGNvbnN0IG9mZnNldFRvSW5kaWNlcyA9ICh2YXJPZmZzZXQ6IHN0cmluZykgPT4ge1xuICAgIGltcGxlbWVudGF0aW9uVXNlZC5vZmZzZXRUb0luZGljZXMgPSB0cnVlO1xuICAgIHJldHVybiByYW5rIDwgMiA/IHZhck9mZnNldCA6IGBvMmlfJHtuYW1lfSgke3Zhck9mZnNldH0pYDtcbiAgfTtcblxuICBjb25zdCBvZmZzZXRzOiBzdHJpbmdbXSA9IFtdO1xuICBpZiAocmFuayA+PSAyKSB7XG4gICAgZm9yIChsZXQgaSA9IHJhbmsgLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgb2Zmc2V0cy5wdXNoKGAke2dldEVsZW1lbnRBdChzdHJpZGVzLCBpLCByYW5rKX0gKiAoaW5kaWNlc1ske2l9XSlgKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBpbmRpY2VzVG9PZmZzZXRJbXBsZW1lbnRhdGlvbiA9XG4gICAgcmFuayA8IDJcbiAgICAgID8gJydcbiAgICAgIDogYFxuICBmbiBpMm9fJHtuYW1lfShpbmRpY2VzOiAke3R5cGUuaW5kaWNlc30pIC0+IHUzMiB7XG4gICAgcmV0dXJuICR7b2Zmc2V0cy5qb2luKCcrJyl9O1xuICB9YDtcblxuICBjb25zdCBpbmRpY2VzVG9PZmZzZXQgPSAodmFySW5kaWNlczogc3RyaW5nKSA9PiB7XG4gICAgaW1wbGVtZW50YXRpb25Vc2VkLmluZGljZXNUb09mZnNldCA9IHRydWU7XG4gICAgcmV0dXJuIHJhbmsgPCAyID8gdmFySW5kaWNlcyA6IGBpMm9fJHtuYW1lfSgke3ZhckluZGljZXN9KWA7XG4gIH07XG5cbiAgY29uc3QgaW5kaWNlcyA9ICguLi5pbml0OiBSZWFkb25seUFycmF5PG51bWJlciB8IHN0cmluZz4pID0+XG4gICAgcmFuayA9PT0gMCA/ICcwdScgOiBgJHt0eXBlLmluZGljZXN9KCR7aW5pdC5tYXAobm9ybWFsaXplRGltKS5qb2luKCcsJyl9KWA7XG5cbiAgY29uc3QgaW5kaWNlc0dldCA9ICh2YXJJbmRpY2VzOiBzdHJpbmcsIGlkeDogbnVtYmVyIHwgc3RyaW5nKSA9PiB7XG4gICAgaWYgKHJhbmsgPCAyKSB7XG4gICAgICByZXR1cm4gYCR7dmFySW5kaWNlc31gO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYCR7Z2V0RWxlbWVudEF0KHZhckluZGljZXMsIGlkeCwgcmFuayl9YDtcbiAgICB9XG4gIH07XG5cbiAgY29uc3QgaW5kaWNlc1NldCA9ICh2YXJJbmRpY2VzOiBzdHJpbmcsIGlkeDogbnVtYmVyIHwgc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSA9PiB7XG4gICAgaWYgKHJhbmsgPCAyKSB7XG4gICAgICByZXR1cm4gYCR7dmFySW5kaWNlc309JHt2YWx1ZX07YDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGAke2dldEVsZW1lbnRBdCh2YXJJbmRpY2VzLCBpZHgsIHJhbmspfT0ke3ZhbHVlfTtgO1xuICAgIH1cbiAgfTtcblxuICBjb25zdCBicm9hZGNhc3RlZEluZGljZXNUb09mZnNldEltcGxlbWVudGF0aW9uOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge307XG4gIGNvbnN0IGJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0ID0gKHZhckluZGljZXM6IHN0cmluZywgb3V0cHV0OiBJbmRpY2VzSGVscGVyKSA9PiB7XG4gICAgaW1wbGVtZW50YXRpb25Vc2VkLmJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0ID0gdHJ1ZTtcbiAgICBjb25zdCBpbXBsS2V5ID0gYCR7b3V0cHV0Lm5hbWV9YnJvYWRjYXN0ZWRJbmRpY2VzVG8ke25hbWV9T2Zmc2V0YDtcbiAgICBpZiAoaW1wbEtleSBpbiBicm9hZGNhc3RlZEluZGljZXNUb09mZnNldEltcGxlbWVudGF0aW9uKSB7XG4gICAgICByZXR1cm4gYCR7aW1wbEtleX0oJHt2YXJJbmRpY2VzfSlgO1xuICAgIH1cbiAgICBjb25zdCBvZmZzZXRzID0gW107XG4gICAgZm9yIChsZXQgaSA9IHJhbmsgLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgY29uc3QgaWR4ID0gb3V0cHV0LmluZGljZXNHZXQoJ291dHB1dEluZGljZXMnLCBpICsgb3V0cHV0LnJhbmsgLSByYW5rKTtcbiAgICAgIG9mZnNldHMucHVzaChgJHtpbmRpY2VzR2V0KHN0cmlkZXMsIGkpfSAqICgke2lkeH0gJSAke2luZGljZXNHZXQoc2hhcGUsIGkpfSlgKTtcbiAgICB9XG4gICAgYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXRJbXBsZW1lbnRhdGlvbltpbXBsS2V5XSA9IGBmbiAke2ltcGxLZXl9KG91dHB1dEluZGljZXM6ICR7b3V0cHV0LnR5cGUuaW5kaWNlc30pIC0+IHUzMiB7XG4gICAgICAgICAgICAgcmV0dXJuICR7b2Zmc2V0cy5sZW5ndGggPiAwID8gb2Zmc2V0cy5qb2luKCcrJykgOiAnMHUnfTtcbiAgICAgICAgICAgfWA7XG5cbiAgICByZXR1cm4gYCR7aW1wbEtleX0oJHt2YXJJbmRpY2VzfSlgO1xuICB9O1xuXG4gIGNvbnN0IHNldEJ5T2Zmc2V0ID0gKG9mZnNldDogbnVtYmVyIHwgc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSA9PlxuICAgICgoKSA9PiB7XG4gICAgICBpZiAodHlwZS5zdG9yYWdlID09PSB0eXBlLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiBgJHtuYW1lfVske29mZnNldH1dPSR7dmFsdWV9O2A7XG4gICAgICB9IGVsc2UgaWYgKHR5cGUuc3RvcmFnZSA9PT0gJ3ZlYzI8dTMyPicgJiYgdHlwZS52YWx1ZSA9PT0gJ2kzMicpIHtcbiAgICAgICAgLy8gaW50NjQsIGNvbXBvbmVudHMgPT09IDFcbiAgICAgICAgcmV0dXJuIGAke25hbWV9WyR7b2Zmc2V0fV09dmVjMjx1MzI+KHUzMigke3ZhbHVlfSksIHNlbGVjdCgwdSwgMHhGRkZGRkZGRnUsICR7dmFsdWV9IDwgMCkpO2A7XG4gICAgICB9IGVsc2UgaWYgKHR5cGUuc3RvcmFnZSA9PT0gJ3ZlYzI8dTMyPicgJiYgdHlwZS52YWx1ZSA9PT0gJ3UzMicpIHtcbiAgICAgICAgLy8gdWludDY0LCBjb21wb25lbnRzID09PSAxXG4gICAgICAgIHJldHVybiBgJHtuYW1lfVske29mZnNldH1dPXZlYzI8dTMyPih1MzIoJHt2YWx1ZX0pLCAwdSk7YDtcbiAgICAgIH0gZWxzZSBpZiAodHlwZS5zdG9yYWdlID09PSAndTMyJyAmJiB0eXBlLnZhbHVlID09PSAndmVjNDxib29sPicpIHtcbiAgICAgICAgLy8gYm9vbCwgY29tcG9uZW50cyA9PT0gNFxuICAgICAgICByZXR1cm4gYCR7bmFtZX1bJHtvZmZzZXR9XT1kb3QodmVjNDx1MzI+KDB4MSwgMHgxMDAsIDB4MTAwMDAsIDB4MTAwMDAwMCksIHZlYzQ8dTMyPigke3ZhbHVlfSkpO2A7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vdCBzdXBwb3J0ZWQgY29tYmluYXRpb24gb2Ygc3RvcmFnZSB0eXBlICR7dHlwZS5zdG9yYWdlfSBhbmQgdmFsdWUgdHlwZSAke3R5cGUudmFsdWV9IHlldGApO1xuICAgICAgfVxuICAgIH0pKCk7XG5cbiAgY29uc3QgZ2V0QnlPZmZzZXQgPSAob2Zmc2V0OiBudW1iZXIgfCBzdHJpbmcpID0+XG4gICAgKCgpID0+IHtcbiAgICAgIGlmICh0eXBlLnN0b3JhZ2UgPT09IHR5cGUudmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGAke25hbWV9WyR7b2Zmc2V0fV1gO1xuICAgICAgfSBlbHNlIGlmICh0eXBlLnN0b3JhZ2UgPT09ICd2ZWMyPHUzMj4nICYmIHR5cGUudmFsdWUgPT09ICdpMzInKSB7XG4gICAgICAgIC8vIGludDY0LCBjb21wb25lbnRzID09PSAxXG4gICAgICAgIHJldHVybiBgaTMyKCR7bmFtZX1bJHtvZmZzZXR9XS54KWA7XG4gICAgICB9IGVsc2UgaWYgKHR5cGUuc3RvcmFnZSA9PT0gJ3ZlYzI8dTMyPicgJiYgdHlwZS52YWx1ZSA9PT0gJ3UzMicpIHtcbiAgICAgICAgLy8gdWludDY0LCBjb21wb25lbnRzID09PSAxXG4gICAgICAgIHJldHVybiBgdTMyKCR7bmFtZX1bJHtvZmZzZXR9XS54KWA7XG4gICAgICB9IGVsc2UgaWYgKHR5cGUuc3RvcmFnZSA9PT0gJ3UzMicgJiYgdHlwZS52YWx1ZSA9PT0gJ3ZlYzQ8Ym9vbD4nKSB7XG4gICAgICAgIC8vIGJvb2wsIGNvbXBvbmVudHMgPT09IDRcbiAgICAgICAgcmV0dXJuIGB2ZWM0PGJvb2w+KGJvb2woJHtuYW1lfVske29mZnNldH1dICYgMHhGRnUpLCBib29sKCR7bmFtZX1bJHtvZmZzZXR9XSAmIDB4RkYwMHUpLCBib29sKCR7bmFtZX1bJHtcbiAgICAgICAgICBvZmZzZXRcbiAgICAgICAgfV0gJiAweEZGMDAwMHUpLCBib29sKCR7bmFtZX1bJHtvZmZzZXR9XSAmIDB4RkYwMDAwMDB1KSlgO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIGNvbWJpbmF0aW9uIG9mIHN0b3JhZ2UgdHlwZSAke3R5cGUuc3RvcmFnZX0gYW5kIHZhbHVlIHR5cGUgJHt0eXBlLnZhbHVlfSB5ZXRgKTtcbiAgICAgIH1cbiAgICB9KSgpO1xuXG4gIGNvbnN0IGdldEJ5SW5kaWNlc0ltcGxlbWVudGF0aW9uID1cbiAgICByYW5rIDwgMlxuICAgICAgPyAnJ1xuICAgICAgOiBgXG4gIGZuIGdldF8ke25hbWV9QnlJbmRpY2VzKGluZGljZXM6ICR7dHlwZS5pbmRpY2VzfSkgLT4gJHt2YWx1ZVR5cGV9IHtcbiAgICByZXR1cm4gJHtnZXRCeU9mZnNldChgaTJvXyR7bmFtZX0oaW5kaWNlcylgKX07XG4gIH1gO1xuXG4gIGNvbnN0IGdldEltcGxlbWVudGF0aW9uID1cbiAgICByYW5rIDwgMlxuICAgICAgPyAnJ1xuICAgICAgOiAoKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGZ1bmN0aW9uUGFyYW1zID0gcmFua0lkZW50aXR5Lm1hcCgoaSkgPT4gYGQke2l9OiB1MzJgKS5qb2luKCcsICcpO1xuICAgICAgICAgIGNvbnN0IGRpbXNQYXJhbXMgPSByYW5rSWRlbnRpdHkubWFwKChpKSA9PiBgZCR7aX1gKS5qb2luKCcsICcpO1xuICAgICAgICAgIHJldHVybiBgXG4gIGZuIGdldF8ke25hbWV9KCR7ZnVuY3Rpb25QYXJhbXN9KSAtPiAke3ZhbHVlVHlwZX0ge1xuICAgIHJldHVybiBnZXRfJHtuYW1lfUJ5SW5kaWNlcygke2luZGljZXMoZGltc1BhcmFtcyl9KTtcbiAgfWA7XG4gICAgICAgIH0pKCk7XG5cbiAgY29uc3QgZ2V0ID0gKC4uLmluZGljZXM6IFJlYWRvbmx5QXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT4ge1xuICAgIGlmIChpbmRpY2VzLmxlbmd0aCAhPT0gcmFuaykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbmRpY2VzIGxlbmd0aCBtdXN0IGJlICR7cmFua31gKTtcbiAgICB9XG5cbiAgICBjb25zdCBub3JtYWxpemVkSW5kaWNlcyA9IGluZGljZXMubWFwKG5vcm1hbGl6ZURpbSkuam9pbignLCcpO1xuXG4gICAgaWYgKHJhbmsgPT09IDApIHtcbiAgICAgIHJldHVybiBnZXRCeU9mZnNldCgnMHUnKTtcbiAgICB9IGVsc2UgaWYgKHJhbmsgPT09IDEpIHtcbiAgICAgIHJldHVybiBnZXRCeU9mZnNldChub3JtYWxpemVkSW5kaWNlc1swXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGltcGxlbWVudGF0aW9uVXNlZC5nZXQgPSB0cnVlO1xuICAgICAgaW1wbGVtZW50YXRpb25Vc2VkLmdldEJ5SW5kaWNlcyA9IHRydWU7XG4gICAgICBpbXBsZW1lbnRhdGlvblVzZWQuaW5kaWNlc1RvT2Zmc2V0ID0gdHJ1ZTtcbiAgICAgIHJldHVybiBgZ2V0XyR7bmFtZX0oJHtub3JtYWxpemVkSW5kaWNlc30pYDtcbiAgICB9XG4gIH07XG5cbiAgY29uc3QgZ2V0QnlJbmRpY2VzID0gKHZhckluZGljZXM6IHN0cmluZykgPT4ge1xuICAgIGlmIChyYW5rIDwgMikge1xuICAgICAgcmV0dXJuIGdldEJ5T2Zmc2V0KHZhckluZGljZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpbXBsZW1lbnRhdGlvblVzZWQuZ2V0QnlJbmRpY2VzID0gdHJ1ZTtcbiAgICAgIGltcGxlbWVudGF0aW9uVXNlZC5pbmRpY2VzVG9PZmZzZXQgPSB0cnVlO1xuICAgICAgcmV0dXJuIGBnZXRfJHtuYW1lfUJ5SW5kaWNlcygke3ZhckluZGljZXN9KWA7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IHNldEJ5SW5kaWNlc0ltcGxlbWVudGF0aW9uID1cbiAgICByYW5rIDwgMlxuICAgICAgPyAnJ1xuICAgICAgOiBgXG4gIGZuIHNldF8ke25hbWV9QnlJbmRpY2VzKGluZGljZXM6ICR7dHlwZS5pbmRpY2VzfSwgdmFsdWU6ICR7dmFsdWVUeXBlfSkge1xuICAgICR7c2V0QnlPZmZzZXQoYGkyb18ke25hbWV9KGluZGljZXMpYCwgJ3ZhbHVlJyl9XG4gIH1gO1xuXG4gIGNvbnN0IHNldEltcGxlbWVudGF0aW9uID1cbiAgICByYW5rIDwgMlxuICAgICAgPyAnJ1xuICAgICAgOiAoKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGZ1bmN0aW9uUGFyYW1zID0gcmFua0lkZW50aXR5Lm1hcCgoaSkgPT4gYGQke2l9OiB1MzJgKS5qb2luKCcsICcpO1xuICAgICAgICAgIGNvbnN0IGRpbXNQYXJhbXMgPSByYW5rSWRlbnRpdHkubWFwKChpKSA9PiBgZCR7aX1gKS5qb2luKCcsICcpO1xuICAgICAgICAgIHJldHVybiBgXG4gIGZuIHNldF8ke25hbWV9KCR7ZnVuY3Rpb25QYXJhbXN9LCB2YWx1ZTogJHt2YWx1ZVR5cGV9KSB7XG4gICAgc2V0XyR7bmFtZX1CeUluZGljZXMoJHtpbmRpY2VzKGRpbXNQYXJhbXMpfSwgdmFsdWUpO1xuICB9YDtcbiAgICAgICAgfSkoKTtcblxuICBjb25zdCBzZXQgPSAoLi4uaW5kaWNlc0FuZFZhbHVlOiBSZWFkb25seUFycmF5PG51bWJlciB8IHN0cmluZz4pID0+IHtcbiAgICBpZiAoaW5kaWNlc0FuZFZhbHVlLmxlbmd0aCAhPT0gcmFuayArIDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW5kaWNlcyBsZW5ndGggbXVzdCBiZSAke3Jhbmt9YCk7XG4gICAgfVxuICAgIGNvbnN0IHZhbHVlID0gaW5kaWNlc0FuZFZhbHVlW3JhbmtdO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ZhbHVlIG11c3QgYmUgc3RyaW5nJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgbm9ybWFsaXplZEluZGljZXMgPSBpbmRpY2VzQW5kVmFsdWUuc2xpY2UoMCwgcmFuaykubWFwKG5vcm1hbGl6ZURpbSkuam9pbignLCcpO1xuXG4gICAgaWYgKHJhbmsgPT09IDApIHtcbiAgICAgIHJldHVybiBzZXRCeU9mZnNldCgnMHUnLCB2YWx1ZSk7XG4gICAgfSBlbHNlIGlmIChyYW5rID09PSAxKSB7XG4gICAgICByZXR1cm4gc2V0QnlPZmZzZXQobm9ybWFsaXplZEluZGljZXNbMF0sIHZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaW1wbGVtZW50YXRpb25Vc2VkLnNldCA9IHRydWU7XG4gICAgICBpbXBsZW1lbnRhdGlvblVzZWQuc2V0QnlJbmRpY2VzID0gdHJ1ZTtcbiAgICAgIGltcGxlbWVudGF0aW9uVXNlZC5pbmRpY2VzVG9PZmZzZXQgPSB0cnVlO1xuICAgICAgcmV0dXJuIGBzZXRfJHtuYW1lfSgke25vcm1hbGl6ZWRJbmRpY2VzfSwgJHt2YWx1ZX0pYDtcbiAgICB9XG4gIH07XG5cbiAgY29uc3Qgc2V0QnlJbmRpY2VzID0gKHZhckluZGljZXM6IHN0cmluZywgdmFsdWU6IHN0cmluZykgPT4ge1xuICAgIGlmIChyYW5rIDwgMikge1xuICAgICAgcmV0dXJuIHNldEJ5T2Zmc2V0KHZhckluZGljZXMsIHZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaW1wbGVtZW50YXRpb25Vc2VkLnNldEJ5SW5kaWNlcyA9IHRydWU7XG4gICAgICBpbXBsZW1lbnRhdGlvblVzZWQuaW5kaWNlc1RvT2Zmc2V0ID0gdHJ1ZTtcbiAgICAgIHJldHVybiBgc2V0XyR7bmFtZX1CeUluZGljZXMoJHt2YXJJbmRpY2VzfSwgJHt2YWx1ZX0pO2A7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGltcGwgPSAoKSA9PiB7XG4gICAgY29uc3QgaW1wbHMgPSBbXTtcbiAgICBsZXQgbmVlZFNoYXBlU3RyaWRlcyA9IGZhbHNlO1xuICAgIGlmIChpbXBsZW1lbnRhdGlvblVzZWQub2Zmc2V0VG9JbmRpY2VzKSB7XG4gICAgICBpbXBscy5wdXNoKG9mZnNldFRvSW5kaWNlc0ltcGxlbWVudGF0aW9uKTtcbiAgICAgIG5lZWRTaGFwZVN0cmlkZXMgPSB0cnVlO1xuICAgIH1cbiAgICBpZiAoaW1wbGVtZW50YXRpb25Vc2VkLmluZGljZXNUb09mZnNldCkge1xuICAgICAgaW1wbHMucHVzaChpbmRpY2VzVG9PZmZzZXRJbXBsZW1lbnRhdGlvbik7XG4gICAgICBuZWVkU2hhcGVTdHJpZGVzID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKGltcGxlbWVudGF0aW9uVXNlZC5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldCkge1xuICAgICAgT2JqZWN0LnZhbHVlcyhicm9hZGNhc3RlZEluZGljZXNUb09mZnNldEltcGxlbWVudGF0aW9uKS5mb3JFYWNoKChpbXBsKSA9PiBpbXBscy5wdXNoKGltcGwpKTtcbiAgICAgIG5lZWRTaGFwZVN0cmlkZXMgPSB0cnVlO1xuICAgIH1cbiAgICBpZiAoaW1wbGVtZW50YXRpb25Vc2VkLnNldCkge1xuICAgICAgaW1wbHMucHVzaChzZXRJbXBsZW1lbnRhdGlvbik7XG4gICAgICBuZWVkU2hhcGVTdHJpZGVzID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKGltcGxlbWVudGF0aW9uVXNlZC5zZXRCeUluZGljZXMpIHtcbiAgICAgIGltcGxzLnB1c2goc2V0QnlJbmRpY2VzSW1wbGVtZW50YXRpb24pO1xuICAgICAgbmVlZFNoYXBlU3RyaWRlcyA9IHRydWU7XG4gICAgfVxuICAgIGlmIChpbXBsZW1lbnRhdGlvblVzZWQuZ2V0KSB7XG4gICAgICBpbXBscy5wdXNoKGdldEltcGxlbWVudGF0aW9uKTtcbiAgICAgIG5lZWRTaGFwZVN0cmlkZXMgPSB0cnVlO1xuICAgIH1cbiAgICBpZiAoaW1wbGVtZW50YXRpb25Vc2VkLmdldEJ5SW5kaWNlcykge1xuICAgICAgaW1wbHMucHVzaChnZXRCeUluZGljZXNJbXBsZW1lbnRhdGlvbik7XG4gICAgICBuZWVkU2hhcGVTdHJpZGVzID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKCF1c2VVbmlmb3JtICYmIG5lZWRTaGFwZVN0cmlkZXMpIHtcbiAgICAgIGltcGxzLnVuc2hpZnQoXG4gICAgICAgIGBjb25zdCAke3NoYXBlfSA9ICR7dHlwZS5pbmRpY2VzfSgke3NoYXBlT3JSYW5rLmpvaW4oJywnKX0pO2AsXG4gICAgICAgIGBjb25zdCAke3N0cmlkZXN9ID0gJHt0eXBlLmluZGljZXN9KCR7U2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKHNoYXBlT3JSYW5rKS5qb2luKCcsJyl9KTtgLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGltcGxzLmpvaW4oJ1xcbicpO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgaW1wbCxcbiAgICB0eXBlLFxuICAgIG9mZnNldFRvSW5kaWNlcyxcbiAgICBpbmRpY2VzVG9PZmZzZXQsXG4gICAgYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQsXG4gICAgaW5kaWNlcyxcbiAgICBpbmRpY2VzR2V0LFxuICAgIGluZGljZXNTZXQsXG4gICAgc2V0LFxuICAgIHNldEJ5T2Zmc2V0LFxuICAgIHNldEJ5SW5kaWNlcyxcbiAgICBnZXQsXG4gICAgZ2V0QnlPZmZzZXQsXG4gICAgZ2V0QnlJbmRpY2VzLFxuICAgIC8vIGlzVmVjNCxcbiAgICB1c2FnZSxcbiAgICBuYW1lLFxuICAgIHN0cmlkZXMsXG4gICAgc2hhcGUsXG4gICAgcmFuayxcbiAgfTtcbn07XG5cbi8qKlxuICogQ3JlYXRlIGEgSW5kaWNlc0hlbHBlciBmb3IgYW4gaW5wdXQuXG4gKlxuICogQHBhcmFtIG5hbWUgLSB0aGUgbmFtZSBvZiB0aGUgaW5wdXQuXG4gKiBAcGFyYW0gdHlwZSAtIHRoZSB0ZW5zb3IgdHlwZSBvZiB0aGUgaW5wdXQuXG4gKiBAcGFyYW0gc2hhcGVPclJhbmsgLSB0aGUgdGVuc29yIHNoYXBlIG9yIHRoZSByYW5rIG9mIHRoZSBpbnB1dC5cbiAqIEBwYXJhbSBjb21wb25lbnRzIC0gdGhlIG51bWJlciBvZiBjb21wb25lbnRzIG9mIHRoZSBpbnB1dC4gYXZhaWxhYmxlIHZhbHVlcyBhcmUgMSwgMiwgMywgNC4gZGVmYXVsdCBpcyAxLlxuICogQHJldHVybnMgYW4gSW5kaWNlc0hlbHBlciBmb3IgdGhlIGlucHV0LlxuICovXG5leHBvcnQgY29uc3QgaW5wdXRWYXJpYWJsZSA9IChcbiAgbmFtZTogc3RyaW5nLFxuICB0eXBlOiBudW1iZXIsXG4gIHNoYXBlT3JSYW5rOiBudW1iZXIgfCByZWFkb25seSBudW1iZXJbXSxcbiAgY29tcG9uZW50czogMSB8IDIgfCAzIHwgNCA9IDEsXG4pOiBJbmRpY2VzSGVscGVyID0+IGNyZWF0ZUluZGljZXNIZWxwZXIobmFtZSwgdHlwZSwgc2hhcGVPclJhbmssICdpbnB1dCcsIGNvbXBvbmVudHMpO1xuXG4vKipcbiAqIENyZWF0ZSBhIEluZGljZXNIZWxwZXIgZm9yIGFuIG91dHB1dC5cbiAqXG4gKiBAcGFyYW0gbmFtZSAtIHRoZSBuYW1lIG9mIHRoZSBvdXRwdXQuXG4gKiBAcGFyYW0gdHlwZSAtIHRoZSB0ZW5zb3IgdHlwZSBvZiB0aGUgb3V0cHV0LlxuICogQHBhcmFtIHNoYXBlT3JSYW5rIC0gdGhlIHRlbnNvciBzaGFwZSBvciB0aGUgcmFuayBvZiB0aGUgb3V0cHV0LlxuICogQHBhcmFtIGNvbXBvbmVudHMgLSB0aGUgbnVtYmVyIG9mIGNvbXBvbmVudHMgb2YgdGhlIG91dHB1dC4gYXZhaWxhYmxlIHZhbHVlcyBhcmUgMSwgMiwgMywgNC4gZGVmYXVsdCBpcyAxLlxuICogQHJldHVybnMgYW4gSW5kaWNlc0hlbHBlciBmb3IgdGhlIG91dHB1dC5cbiAqL1xuZXhwb3J0IGNvbnN0IG91dHB1dFZhcmlhYmxlID0gKFxuICBuYW1lOiBzdHJpbmcsXG4gIHR5cGU6IG51bWJlcixcbiAgc2hhcGVPclJhbms6IG51bWJlciB8IHJlYWRvbmx5IG51bWJlcltdLFxuICBjb21wb25lbnRzOiAxIHwgMiB8IDMgfCA0ID0gMSxcbik6IEluZGljZXNIZWxwZXIgPT4gY3JlYXRlSW5kaWNlc0hlbHBlcihuYW1lLCB0eXBlLCBzaGFwZU9yUmFuaywgJ291dHB1dCcsIGNvbXBvbmVudHMpO1xuXG4vKipcbiAqIENyZWF0ZSBhIEluZGljZXNIZWxwZXIgZm9yIGFuIGF0b21pYyBvdXRwdXQuXG4gKlxuICogQHBhcmFtIG5hbWUgLSB0aGUgbmFtZSBvZiB0aGUgb3V0cHV0LlxuICogQHBhcmFtIHR5cGUgLSB0aGUgdGVuc29yIHR5cGUgb2YgdGhlIG91dHB1dC5cbiAqIEBwYXJhbSBzaGFwZU9yUmFuayAtIHRoZSB0ZW5zb3Igc2hhcGUgb3IgdGhlIHJhbmsgb2YgdGhlIG91dHB1dC5cbiAqIEByZXR1cm5zIGFuIEluZGljZXNIZWxwZXIgZm9yIHRoZSBvdXRwdXQuXG4gKi9cbmV4cG9ydCBjb25zdCBhdG9taWNPdXRwdXRWYXJpYWJsZSA9IChcbiAgbmFtZTogc3RyaW5nLFxuICB0eXBlOiBudW1iZXIsXG4gIHNoYXBlT3JSYW5rOiBudW1iZXIgfCByZWFkb25seSBudW1iZXJbXSxcbik6IEluZGljZXNIZWxwZXIgPT4gY3JlYXRlSW5kaWNlc0hlbHBlcihuYW1lLCB0eXBlLCBzaGFwZU9yUmFuaywgJ2F0b21pY091dHB1dCcsIDEpO1xuXG4vKipcbiAqIENyZWF0ZSBhIEluZGljZXNIZWxwZXIgZm9yIGFuIGludGVybmFsIHZhcmlhYmxlLlxuICpcbiAqIEBwYXJhbSBuYW1lIC0gdGhlIG5hbWUgb2YgdGhlIHZhcmlhYmxlLlxuICogQHBhcmFtIHR5cGUgLSB0aGUgdGVuc29yIHR5cGUgb2YgdGhlIHZhcmlhYmxlLlxuICogQHBhcmFtIHNoYXBlT3JSYW5rIC0gdGhlIHRlbnNvciBzaGFwZSBvciB0aGUgcmFuayBvZiB0aGUgdmFyaWFibGUuXG4gKiBAcGFyYW0gY29tcG9uZW50cyAtIHRoZSBudW1iZXIgb2YgY29tcG9uZW50cyBvZiB0aGUgdmFyaWFibGUuIGF2YWlsYWJsZSB2YWx1ZXMgYXJlIDEsIDIsIDMsIDQuIGRlZmF1bHQgaXMgMS5cbiAqIEByZXR1cm5zIGFuIEluZGljZXNIZWxwZXIgZm9yIHRoZSB2YXJpYWJsZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGludGVybmFsVmFyaWFibGUgPSAoXG4gIG5hbWU6IHN0cmluZyxcbiAgdHlwZTogbnVtYmVyLFxuICBzaGFwZU9yUmFuazogbnVtYmVyIHwgcmVhZG9ubHkgbnVtYmVyW10sXG4gIGNvbXBvbmVudHM6IDEgfCAyIHwgMyB8IDQgPSAxLFxuKTogSW5kaWNlc0hlbHBlciA9PiBjcmVhdGVJbmRpY2VzSGVscGVyKG5hbWUsIHR5cGUsIHNoYXBlT3JSYW5rLCAnaW50ZXJuYWwnLCBjb21wb25lbnRzKTtcblxuZXhwb3J0IHR5cGUgVW5pZm9ybURhdGFFbGVtZW50VHlwZSA9ICd1MzInIHwgJ2YxNicgfCAnZjMyJyB8ICdpMzInO1xuZXhwb3J0IHR5cGUgVW5pZm9ybXNBcnJheVR5cGUgPSBBcnJheTx7IG5hbWU6IHN0cmluZzsgdHlwZTogVW5pZm9ybURhdGFFbGVtZW50VHlwZTsgbGVuZ3RoPzogbnVtYmVyIH0+O1xuXG4vKipcbiAqIEEgU2hhZGVySGVscGVyIGlzIGEgaGVscGVyIGNsYXNzIGZvciBnZW5lcmF0aW5nIFdHU0wgY29kZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTaGFkZXJIZWxwZXIge1xuICAvKipcbiAgICogQSBoZWxwZXIgZnVuY3Rpb24gdG8gZ2VuZXJhdGUgdGhlIHN0YXJ0IG9mIG1haW4gZnVuY3Rpb24gaW4gV0dTTCBzb3VyY2UgY29kZS5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gICAqICAuLi5cbiAgICpcbiAgICogICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgKiAgICAvLyB5b3VyIGNvZGUgaGVyZSBpbnNpZGUgbWFpbigpIGZ1bmN0aW9uXG4gICAqICAgIC4uLlxuICAgKiAgfVxuICAgKiBgO1xuICAgKlxuICAgKiBAcGFyYW0gd29ya2dyb3VwU2l6ZSAtIGFuIG9wdGlvbmFsIHdvcmtncm91cCBzaXplLiBkZWZhdWx0IGlzIFdPUktHUk9VUF9TSVpFLlxuICAgKi9cbiAgbWFpblN0YXJ0KHdvcmtncm91cFNpemU/OiBudW1iZXIgfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgaGVscGVyIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIHRoZSBjb2RlIHNuaXBwZXQgZm9yIGd1YXJkaW5nIGFnYWluc3Qgb3V0LW9mLWJvdW5kcyBzaXplLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcbiAgICogIC4uLlxuICAgKlxuICAgKiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAqICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMob3V0cHV0U2l6ZSl9XG4gICAqXG4gICAqICAgIC8vIHlvdXIgY29kZSBoZXJlIGluc2lkZSBtYWluKCkgZnVuY3Rpb25cbiAgICogICAgLi4uXG4gICAqICB9XG4gICAqIGA7XG4gICAqXG4gICAqIEBwYXJhbSBzaXplIC0gdGhlIHNpemUgb2YgdGhlIGRhdGEgdG8gZ3VhcmQgYWdhaW5zdC4gY2FuIGJlIGEgbnVtYmVyIG9yIGEgc3RyaW5nIChXR1NMIGB1MzJgIGV4cHJlc3Npb24pLlxuICAgKi9cbiAgZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcyhzaXplOiB1bmtub3duKTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIGhlbHBlciBmdW5jdGlvbiB0byBnZW5lcmF0ZSB0aGUgY29kZSBzbmlwcGV0IGZvciBkZWNsYXJpbmcgbXVsdGlwbGUgaW5wdXRzIG9yIG91dHB1dHMuXG4gICAqXG4gICAqIEBwYXJhbSB2YXJpYWJsZXMgLSBhbiBhcnJheSBvZiBJbmRpY2VzSGVscGVyIGZvciB0aGUgdmFyaWFibGVzLlxuICAgKi9cbiAgZGVjbGFyZVZhcmlhYmxlcyguLi52YXJpYWJsZXM6IEluZGljZXNIZWxwZXJbXSk6IHN0cmluZztcblxuICAvKipcbiAgICogQSBoZWxwZXIgZnVuY3Rpb24gdG8gcmVnaXN0ZXIgb25lIHVuaWZvcm0uIENhbiBiZSBjYWxsZWQgbXVsdGlwbGUgdGltZXMgdG8gcmVnaXN0ZXIgbXVsdGlwbGUgdW5pZm9ybXMuXG4gICAqXG4gICAqIEBwYXJhbSBuYW1lIC0gdGhlIG5hbWUgb2YgdGhlIHVuaWZvcm0uXG4gICAqIEBwYXJhbSB0eXBlIC0gdGhlIHR5cGUgb2YgdGhlIHVuaWZvcm0uXG4gICAqIEBwYXJhbSBsZW5ndGggLSB0aGUgbGVuZ3RoIG9mIHRoZSB1bmlmb3JtLCBkZWZhdWx0IHRvIDEgd2hlbiBpdCBpcyBub3QgcHJvdmlkZWQuXG4gICAqL1xuICByZWdpc3RlclVuaWZvcm0obmFtZTogc3RyaW5nLCB0eXBlOiBzdHJpbmcsIGxlbmd0aD86IG51bWJlcik6IFNoYWRlckhlbHBlcjtcblxuICAvKipcbiAgICogQSBoZWxwZXIgZnVuY3Rpb24gdG8gcmVnaXN0ZXIgbXVsdGlwbGUgdW5pZm9ybXMuIENhbiBiZSBjYWxsZWQgbXVsdGlwbGUgdGltZXMgdG8gcmVnaXN0ZXIgbXVsdGlwbGUgdW5pZm9ybXMuXG4gICAqXG4gICAqIEBwYXJhbSB1bmlmb3JtcyAtIGFuIGFycmF5IG9mIHVuaWZvcm1zLiBFYWNoIGVsZW1lbnQgb2YgdGhlIGFycmF5IGlzIGFuIG9iamVjdCB3aXRoIDIgcHJvcGVydGllczogYG5hbWVgIGFuZFxuICAgKiAgICAgYHR5cGVgLlxuICAgKi9cbiAgcmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUpOiBTaGFkZXJIZWxwZXI7XG5cbiAgLyoqXG4gICAqIEEgaGVscGVyIGZ1bmN0aW9uIHRvIHJlZ2lzdGVyIG11bHRpcGxlIGludGVybmFsIHZhcmlhYmxlcy4gQ2FuIGJlIGNhbGxlZCBtdWx0aXBsZSB0aW1lcyB0byByZWdpc3RlciBtdWx0aXBsZVxuICAgKiBpbnRlcm5hbCB2YXJpYWJsZXMuXG4gICAqXG4gICAqIEBwYXJhbSB2YXJpYWJsZXMgLSBhbiBhcnJheSBvZiBJbmRpY2VzSGVscGVyIGZvciB0aGUgdmFyaWFibGVzLlxuICAgKi9cbiAgcmVnaXN0ZXJJbnRlcm5hbFZhcmlhYmxlcyguLi52YXJpYWJsZXM6IEluZGljZXNIZWxwZXJbXSk6IFNoYWRlckhlbHBlcjtcbn1cblxuY2xhc3MgU2hhZGVySGVscGVySW1wbCBpbXBsZW1lbnRzIFNoYWRlckhlbHBlciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgbm9ybWFsaXplZERpc3BhdGNoR3JvdXA6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgICBwcml2YXRlIGxpbWl0czogR1BVU3VwcG9ydGVkTGltaXRzLFxuICApIHt9XG5cbiAgZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcyhzaXplOiBudW1iZXIgfCBzdHJpbmcpOiBzdHJpbmcge1xuICAgIC8vIEd1YXJkIGFnYWluc3Qgb3V0LW9mLWJvdW5kcyB3b3JrIGdyb3VwIHNpemVzXG4gICAgY29uc3Qgc2l6ZUluQ29kZSA9IHR5cGVvZiBzaXplID09PSAnbnVtYmVyJyA/IGAke3NpemV9dWAgOiBzaXplO1xuICAgIHJldHVybiBgaWYgKGdsb2JhbF9pZHggPj0gJHtzaXplSW5Db2RlfSkgeyByZXR1cm47IH1gO1xuICB9XG5cbiAgbWFpblN0YXJ0KHdvcmtncm91cFNpemU6IG51bWJlciB8IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9IFdPUktHUk9VUF9TSVpFKSB7XG4gICAgY29uc3Qgd29ya2dyb3VwU2l6ZVggPSB0eXBlb2Ygd29ya2dyb3VwU2l6ZSA9PT0gJ251bWJlcicgPyB3b3JrZ3JvdXBTaXplIDogd29ya2dyb3VwU2l6ZVswXTtcbiAgICBjb25zdCB3b3JrZ3JvdXBTaXplWSA9IHR5cGVvZiB3b3JrZ3JvdXBTaXplID09PSAnbnVtYmVyJyA/IDEgOiB3b3JrZ3JvdXBTaXplWzFdO1xuICAgIGNvbnN0IHdvcmtncm91cFNpemVaID0gdHlwZW9mIHdvcmtncm91cFNpemUgPT09ICdudW1iZXInID8gMSA6IHdvcmtncm91cFNpemVbMl07XG5cbiAgICBpZiAoXG4gICAgICB3b3JrZ3JvdXBTaXplWCA+IHRoaXMubGltaXRzLm1heENvbXB1dGVXb3JrZ3JvdXBTaXplWCB8fFxuICAgICAgd29ya2dyb3VwU2l6ZVkgPiB0aGlzLmxpbWl0cy5tYXhDb21wdXRlV29ya2dyb3VwU2l6ZVkgfHxcbiAgICAgIHdvcmtncm91cFNpemVaID4gdGhpcy5saW1pdHMubWF4Q29tcHV0ZVdvcmtncm91cFNpemVaXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGB3b3JrZ3JvdXAgc2l6ZSBbJHt3b3JrZ3JvdXBTaXplWH0sICR7d29ya2dyb3VwU2l6ZVl9LCAke1xuICAgICAgICAgIHdvcmtncm91cFNpemVaXG4gICAgICAgIH1dIGV4Y2VlZHMgdGhlIG1heGltdW0gd29ya2dyb3VwIHNpemUgWyR7dGhpcy5saW1pdHMubWF4Q29tcHV0ZVdvcmtncm91cFNpemVYfSwgJHtcbiAgICAgICAgICB0aGlzLmxpbWl0cy5tYXhDb21wdXRlV29ya2dyb3VwU2l6ZVlcbiAgICAgICAgfSwgJHt0aGlzLmxpbWl0cy5tYXhDb21wdXRlV29ya2dyb3VwU2l6ZVp9XS5gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAod29ya2dyb3VwU2l6ZVggKiB3b3JrZ3JvdXBTaXplWSAqIHdvcmtncm91cFNpemVaID4gdGhpcy5saW1pdHMubWF4Q29tcHV0ZUludm9jYXRpb25zUGVyV29ya2dyb3VwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGB3b3JrZ3JvdXAgc2l6ZSBbJHt3b3JrZ3JvdXBTaXplWH0sICR7d29ya2dyb3VwU2l6ZVl9LCAke1xuICAgICAgICAgIHdvcmtncm91cFNpemVaXG4gICAgICAgIH1dIGV4Y2VlZHMgdGhlIG1heGltdW0gd29ya2dyb3VwIGludm9jYXRpb25zICR7dGhpcy5saW1pdHMubWF4Q29tcHV0ZUludm9jYXRpb25zUGVyV29ya2dyb3VwfS5gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBpczFEaW1lbnNpb25EaXNwYXRjaCA9IHRoaXMubm9ybWFsaXplZERpc3BhdGNoR3JvdXBbMV0gPT09IDEgJiYgdGhpcy5ub3JtYWxpemVkRGlzcGF0Y2hHcm91cFsyXSA9PT0gMTtcbiAgICBjb25zdCBwYXJhbUxpc3QgPSBpczFEaW1lbnNpb25EaXNwYXRjaFxuICAgICAgPyBgQGJ1aWx0aW4oZ2xvYmFsX2ludm9jYXRpb25faWQpIGdsb2JhbF9pZCA6IHZlYzM8dTMyPixcbiAgICBAYnVpbHRpbih3b3JrZ3JvdXBfaWQpIHdvcmtncm91cF9pZCA6IHZlYzM8dTMyPixcbiAgICBAYnVpbHRpbihsb2NhbF9pbnZvY2F0aW9uX2luZGV4KSBsb2NhbF9pZHggOiB1MzIsXG4gICAgQGJ1aWx0aW4obG9jYWxfaW52b2NhdGlvbl9pZCkgbG9jYWxfaWQgOiB2ZWMzPHUzMj5gXG4gICAgICA6IGBAYnVpbHRpbihnbG9iYWxfaW52b2NhdGlvbl9pZCkgZ2xvYmFsX2lkIDogdmVjMzx1MzI+LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGJ1aWx0aW4obG9jYWxfaW52b2NhdGlvbl9pZCkgbG9jYWxfaWQgOiB2ZWMzPHUzMj4sXG4gICAgQGJ1aWx0aW4obG9jYWxfaW52b2NhdGlvbl9pbmRleCkgbG9jYWxfaWR4IDogdTMyLFxuICAgIEBidWlsdGluKHdvcmtncm91cF9pZCkgd29ya2dyb3VwX2lkIDogdmVjMzx1MzI+LFxuICAgIEBidWlsdGluKG51bV93b3JrZ3JvdXBzKSBudW1fd29ya2dyb3VwcyA6IHZlYzM8dTMyPmA7XG4gICAgY29uc3QgZ2xvYmFsSWR4RGVmaW5pdGlvbiA9IGlzMURpbWVuc2lvbkRpc3BhdGNoXG4gICAgICA/IGBsZXQgZ2xvYmFsX2lkeCA9IGdsb2JhbF9pZC54O1xuICAgICAgICAgbGV0IHdvcmtncm91cF9pbmRleCA9IHdvcmtncm91cF9pZC54O2BcbiAgICAgIDogYGxldCB3b3JrZ3JvdXBfaW5kZXggPSB3b3JrZ3JvdXBfaWQueiAqIG51bV93b3JrZ3JvdXBzWzBdICogbnVtX3dvcmtncm91cHNbMV0gK1xuICAgICAgICAgICAgIHdvcmtncm91cF9pZC55ICogbnVtX3dvcmtncm91cHNbMF0gKyB3b3JrZ3JvdXBfaWQueDtcbiAgICAgICAgIGxldCBnbG9iYWxfaWR4ID0gd29ya2dyb3VwX2luZGV4ICogJHt3b3JrZ3JvdXBTaXplWCAqIHdvcmtncm91cFNpemVZICogd29ya2dyb3VwU2l6ZVp9dSArIGxvY2FsX2lkeDtgO1xuXG4gICAgcmV0dXJuIGBAY29tcHV0ZSBAd29ya2dyb3VwX3NpemUoJHt3b3JrZ3JvdXBTaXplWH0sICR7d29ya2dyb3VwU2l6ZVl9LCAke3dvcmtncm91cFNpemVafSlcbiAgZm4gbWFpbigke3BhcmFtTGlzdH0pIHtcbiAgICAke2dsb2JhbElkeERlZmluaXRpb259XG4gIGA7XG4gIH1cblxuICBwcml2YXRlIGFwcGVuZFZhcmlhYmxlVW5pZm9ybXModmFyaWFibGU6IEluZGljZXNIZWxwZXIpOiB2b2lkIHtcbiAgICBpZiAodmFyaWFibGUucmFuayAhPT0gMCkge1xuICAgICAgaWYgKHZhcmlhYmxlLnNoYXBlLnN0YXJ0c1dpdGgoJ3VuaWZvcm1zLicpKSB7XG4gICAgICAgIHRoaXMudW5pZm9ybXMucHVzaCh7IG5hbWU6IHZhcmlhYmxlLnNoYXBlLnJlcGxhY2UoJ3VuaWZvcm1zLicsICcnKSwgdHlwZTogJ3UzMicsIGxlbmd0aDogdmFyaWFibGUucmFuayB9KTtcbiAgICAgIH1cbiAgICAgIGlmICh2YXJpYWJsZS5zdHJpZGVzLnN0YXJ0c1dpdGgoJ3VuaWZvcm1zLicpKSB7XG4gICAgICAgIHRoaXMudW5pZm9ybXMucHVzaCh7IG5hbWU6IHZhcmlhYmxlLnN0cmlkZXMucmVwbGFjZSgndW5pZm9ybXMuJywgJycpLCB0eXBlOiAndTMyJywgbGVuZ3RoOiB2YXJpYWJsZS5yYW5rIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZGVjbGFyZVZhcmlhYmxlKHZhcmlhYmxlOiBJbmRpY2VzSGVscGVyLCBiaW5kaW5nSW5kZXg6IG51bWJlcik6IHN0cmluZyB7XG4gICAgaWYgKHZhcmlhYmxlLnVzYWdlID09PSAnaW50ZXJuYWwnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCB1c2UgaW50ZXJuYWwgdmFyaWFibGUgd2l0aCBkZWNsYXJlVmFyaWFibGUoKS4gdXNlIHJlZ2lzdGVySW50ZXJuYWxWYXJpYWJsZXMoKSBpbnN0ZWFkLicpO1xuICAgIH1cbiAgICB0aGlzLnZhcmlhYmxlcy5wdXNoKHZhcmlhYmxlKTtcbiAgICB0aGlzLmFwcGVuZFZhcmlhYmxlVW5pZm9ybXModmFyaWFibGUpO1xuICAgIGNvbnN0IGFjY2VzcyA9IHZhcmlhYmxlLnVzYWdlID09PSAnaW5wdXQnID8gJ3JlYWQnIDogJ3JlYWRfd3JpdGUnO1xuICAgIGNvbnN0IHN0b3JhZ2VUeXBlID0gdmFyaWFibGUudXNhZ2UgPT09ICdhdG9taWNPdXRwdXQnID8gYGF0b21pYzxpMzI+YCA6IHZhcmlhYmxlLnR5cGUuc3RvcmFnZTtcbiAgICByZXR1cm4gYEBncm91cCgwKSBAYmluZGluZygke2JpbmRpbmdJbmRleH0pIHZhcjxzdG9yYWdlLCAke2FjY2Vzc30+ICR7dmFyaWFibGUubmFtZX06IGFycmF5PCR7c3RvcmFnZVR5cGV9PjtgO1xuICB9XG5cbiAgZGVjbGFyZVZhcmlhYmxlcyguLi52YXJpYWJsZXM6IEluZGljZXNIZWxwZXJbXSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHZhcmlhYmxlcy5tYXAoKHYpID0+IHRoaXMuZGVjbGFyZVZhcmlhYmxlKHYsIHRoaXMudmFyaWFibGVJbmRleCsrKSkuam9pbignXFxuJyk7XG4gIH1cblxuICBwcml2YXRlIHJlZ2lzdGVySW50ZXJuYWxWYXJpYWJsZSh2YXJpYWJsZTogSW5kaWNlc0hlbHBlcik6IHZvaWQge1xuICAgIGlmICh2YXJpYWJsZS51c2FnZSAhPT0gJ2ludGVybmFsJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnY2Fubm90IHVzZSBpbnB1dCBvciBvdXRwdXQgdmFyaWFibGUgd2l0aCByZWdpc3RlckludGVybmFsVmFyaWFibGUoKS4gdXNlIGRlY2xhcmVWYXJpYWJsZXMoKSBpbnN0ZWFkLicsXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMuaW50ZXJuYWxWYXJpYWJsZXMucHVzaCh2YXJpYWJsZSk7XG4gICAgdGhpcy5hcHBlbmRWYXJpYWJsZVVuaWZvcm1zKHZhcmlhYmxlKTtcbiAgfVxuXG4gIHJlZ2lzdGVySW50ZXJuYWxWYXJpYWJsZXMoLi4udmFyaWFibGVzOiBJbmRpY2VzSGVscGVyW10pOiBTaGFkZXJIZWxwZXIge1xuICAgIHZhcmlhYmxlcy5mb3JFYWNoKCh2KSA9PiB0aGlzLnJlZ2lzdGVySW50ZXJuYWxWYXJpYWJsZSh2KSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICByZWdpc3RlclVuaWZvcm0obmFtZTogc3RyaW5nLCB0eXBlOiBVbmlmb3JtRGF0YUVsZW1lbnRUeXBlLCBsZW5ndGggPSAxKTogU2hhZGVySGVscGVyIHtcbiAgICB0aGlzLnVuaWZvcm1zLnB1c2goeyBuYW1lLCB0eXBlLCBsZW5ndGggfSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICByZWdpc3RlclVuaWZvcm1zKGFkZGl0aW9uYWxVbmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUpOiBTaGFkZXJIZWxwZXIge1xuICAgIHRoaXMudW5pZm9ybXMgPSB0aGlzLnVuaWZvcm1zLmNvbmNhdChhZGRpdGlvbmFsVW5pZm9ybXMpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFZhcmlhYmxlczogSW5kaWNlc0hlbHBlcltdID0gW107XG4gIHByaXZhdGUgdmFyaWFibGVzOiBJbmRpY2VzSGVscGVyW10gPSBbXTtcbiAgcHJpdmF0ZSB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXTtcbiAgcHJpdmF0ZSB1bmlmb3JtRGVjbGFyYXRpb24oKTogc3RyaW5nIHtcbiAgICBpZiAodGhpcy51bmlmb3Jtcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG5cbiAgICBjb25zdCB1bmlmb3JtU25pcHBldHM6IHN0cmluZ1tdID0gW107XG4gICAgZm9yIChjb25zdCB7IG5hbWUsIHR5cGUsIGxlbmd0aCB9IG9mIHRoaXMudW5pZm9ybXMpIHtcbiAgICAgIGlmIChsZW5ndGggJiYgbGVuZ3RoID4gNCkge1xuICAgICAgICBpZiAodHlwZSA9PT0gJ2YxNicpIHtcbiAgICAgICAgICB1bmlmb3JtU25pcHBldHMucHVzaChgQGFsaWduKDE2KSAke25hbWV9OmFycmF5PG1hdDJ4NDwke3R5cGV9PiwgJHtNYXRoLmNlaWwobGVuZ3RoIC8gOCl9PmApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHVuaWZvcm1TbmlwcGV0cy5wdXNoKGAke25hbWV9OmFycmF5PHZlYzQ8JHt0eXBlfT4sICR7TWF0aC5jZWlsKGxlbmd0aCAvIDQpfT5gKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgdHlwZVRlbXAgPSBsZW5ndGggPT0gbnVsbCB8fCBsZW5ndGggPT09IDEgPyB0eXBlIDogYHZlYyR7bGVuZ3RofTwke3R5cGV9PmA7XG4gICAgICAgIHVuaWZvcm1TbmlwcGV0cy5wdXNoKGAke25hbWV9OiR7dHlwZVRlbXB9YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGBcbiAgICAgIHN0cnVjdCBVbmlmb3JtcyB7ICR7dW5pZm9ybVNuaXBwZXRzLmpvaW4oJywgJyl9IH07XG4gICAgICBAZ3JvdXAoMCkgQGJpbmRpbmcoJHt0aGlzLnZhcmlhYmxlSW5kZXh9KSB2YXI8dW5pZm9ybT4gdW5pZm9ybXM6IFVuaWZvcm1zO2A7XG4gIH1cbiAgcHJpdmF0ZSB2YXJpYWJsZUluZGV4ID0gMDtcblxuICAvKipcbiAgICogR2V0IGFkZGl0aW9uYWwgaW1wbGVtZW50YXRpb24gdGhhdCBuZWVkcyB0byBiZSBhZGRlZCB0byB0aGUgc2hhZGVyIHNvdXJjZS5cbiAgICovXG4gIGdldCBhZGRpdGlvbmFsSW1wbGVtZW50YXRpb25zKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMudW5pZm9ybURlY2xhcmF0aW9uKCkgK1xuICAgICAgdGhpcy52YXJpYWJsZXMubWFwKChpKSA9PiBpLmltcGwoKSkuam9pbignXFxuJykgK1xuICAgICAgdGhpcy5pbnRlcm5hbFZhcmlhYmxlcy5tYXAoKGkpID0+IGkuaW1wbCgpKS5qb2luKCdcXG4nKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSB2YXJpYWJsZSBpbmZvIG9mIHRoZSBzaGFkZXIgcHJvZ3JhbS5cbiAgICovXG4gIGdldCB2YXJpYWJsZXNJbmZvKCk6IFByb2dyYW1Vbmlmb3JtVmFyaWFibGVJbmZvW10gfCB1bmRlZmluZWQge1xuICAgIGlmICh0aGlzLnVuaWZvcm1zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCB1bmlmb3JtV2dzbFR5cGVUb0RhdGFUeXBlID0gKHR5cGU6IFVuaWZvcm1EYXRhRWxlbWVudFR5cGUpID0+XG4gICAgICBbRGF0YVR5cGUudWludDMyLCBEYXRhVHlwZS5mbG9hdDE2LCBEYXRhVHlwZS5mbG9hdCwgRGF0YVR5cGUuaW50MzJdW1sndTMyJywgJ2YxNicsICdmMzInLCAnaTMyJ10uaW5kZXhPZih0eXBlKV07XG4gICAgcmV0dXJuIHRoaXMudW5pZm9ybXMubWFwKCh1KSA9PiBbdW5pZm9ybVdnc2xUeXBlVG9EYXRhVHlwZSh1LnR5cGUpLCB1Lmxlbmd0aCA/PyAxXSk7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVNoYWRlckhlbHBlciA9IChkaXNwYXRjaEdyb3VwOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sIGxpbWl0czogR1BVU3VwcG9ydGVkTGltaXRzKSA9PlxuICBuZXcgU2hhZGVySGVscGVySW1wbChkaXNwYXRjaEdyb3VwLCBsaW1pdHMpO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbyB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsIEluZGljZXNIZWxwZXIsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNwb3NlQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IHBlcm06IG51bWJlcltdO1xufVxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgcGVybTogcmVhZG9ubHkgbnVtYmVyW10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignVHJhbnNwb3NlIHJlcXVpcmVzIDEgaW5wdXQuJyk7XG4gIH1cblxuICBpZiAocGVybS5sZW5ndGggIT09IDAgJiYgcGVybS5sZW5ndGggIT09IGlucHV0c1swXS5kaW1zLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgcGVybSBzaXplICR7cGVybS5sZW5ndGh9IGRvZXMgbm90IG1hdGNoIGlucHV0IHJhbmsgJHtpbnB1dHNbMF0uZGltcy5sZW5ndGh9YCk7XG4gIH1cbn07XG5cbmNvbnN0IGdldEFkanVzdGVkUGVybSA9IChpbnB1dFJhbms6IG51bWJlciwgcGVybTogbnVtYmVyW10pOiBudW1iZXJbXSA9PlxuICBwZXJtLmxlbmd0aCAhPT0gMCA/IHBlcm0gOiBbLi4ubmV3IEFycmF5KGlucHV0UmFuaykua2V5cygpXS5yZXZlcnNlKCk7XG5cbmNvbnN0IGdldE91dHB1dFNoYXBlID0gKGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBwZXJtOiBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdID0+XG4gIFNoYXBlVXRpbC5zb3J0QmFzZWRPblBlcm0oaW5wdXRTaGFwZSwgZ2V0QWRqdXN0ZWRQZXJtKGlucHV0U2hhcGUubGVuZ3RoLCBwZXJtKSk7XG5cbmNvbnN0IHBlcm1GdW5jdGlvbkJvZHkgPSAocGVybTogbnVtYmVyW10sIHJhbms6IG51bWJlciwgaW5wdXQ6IEluZGljZXNIZWxwZXIsIG91dHB1dDogSW5kaWNlc0hlbHBlcik6IHN0cmluZyA9PiB7XG4gIGxldCByZXZlcnNlRnVuYyA9IGBmbiBwZXJtKGk6ICR7b3V0cHV0LnR5cGUuaW5kaWNlc30pIC0+ICR7aW5wdXQudHlwZS5pbmRpY2VzfSB7XG4gICAgdmFyIGE6ICR7aW5wdXQudHlwZS5pbmRpY2VzfTtgO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbms7ICsraSkge1xuICAgIC8vIGlucHV0IGluZGljZXMgYW5kIG91dHB1dCBpbmRpY2VzIHNob3VsZCBhbHdheXMgYmUgbGFyZ2VyIG9yIGVxdWFsIHRvIDIsXG4gICAgLy8gc28gaW5kZXhlciBpcyBhbHdheXMgdmFsaWQgdG8gYmUgdXNlZCBvbiBgYWAgYW5kIGBpYC5cbiAgICByZXZlcnNlRnVuYyArPSBgYVske3Blcm1baV19XT1pWyR7aX1dO2A7XG4gIH1cbiAgcmV0dXJuIChyZXZlcnNlRnVuYyArPSAncmV0dXJuIGE7fScpO1xufTtcblxuY29uc3Qgc3F1ZWV6ZVNoYXBlID0gKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgYWRqdXN0ZWRQZXJtOiBudW1iZXJbXSk6IHsgbmV3U2hhcGU6IG51bWJlcltdOyBuZXdQZXJtOiBudW1iZXJbXSB9ID0+IHtcbiAgY29uc3QgbmV3U2hhcGU6IG51bWJlcltdID0gW107XG4gIGNvbnN0IG5ld1Blcm06IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc2hhcGUubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoc2hhcGVbaV0gIT09IDEpIHtcbiAgICAgIG5ld1NoYXBlLnB1c2goc2hhcGVbaV0pO1xuICAgIH1cbiAgICBpZiAoc2hhcGVbYWRqdXN0ZWRQZXJtW2ldXSAhPT0gMSkge1xuICAgICAgbmV3UGVybS5wdXNoKGFkanVzdGVkUGVybVtpXSk7XG4gICAgfVxuICB9XG4gIHJldHVybiB7IG5ld1NoYXBlLCBuZXdQZXJtIH07XG59O1xuXG5jb25zdCBpc1RyYW5zcG9zZVJlc2hhcGUgPSAocGVybTogbnVtYmVyW10sIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSkgPT4ge1xuICAvLyBBcyBsb25nIGFzIHRoZSBkaW1zIHdpdGggdmFsdWVzID4gMSBzdGF5IGluIHRoZSBzYW1lIG9yZGVyLCBpdCdzIGEgcmVzaGFwZS5cbiAgLy8gRXhhbXBsZTogU2hhcGU9KDEsMSwxMDI0LDQwOTYpIC0+IHBlcm09KDIsMCwzLDEpLlxuICBsZXQgbGFzdFBlcm11dGVkQXhpcyA9IDA7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcGVybS5sZW5ndGg7ICsraSkge1xuICAgIGlmIChzaGFwZVtwZXJtW2ldXSA9PT0gMSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmIChwZXJtW2ldIDwgbGFzdFBlcm11dGVkQXhpcykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBsYXN0UGVybXV0ZWRBeGlzID0gcGVybVtpXTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyA9IChpbnB1dFRlbnNvcjogVGVuc29yVmlldywgcGVybUF0dHI6IG51bWJlcltdKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBpbnB1dERhdGFUeXBlID0gaW5wdXRUZW5zb3IuZGF0YVR5cGU7XG4gIGNvbnN0IGlucHV0UmFuayA9IGlucHV0VGVuc29yLmRpbXMubGVuZ3RoO1xuICBjb25zdCBwZXJtID0gZ2V0QWRqdXN0ZWRQZXJtKGlucHV0UmFuaywgcGVybUF0dHIpO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGdldE91dHB1dFNoYXBlKGlucHV0VGVuc29yLmRpbXMsIHBlcm0pO1xuICBsZXQgbmV3SW5wdXRTaGFwZSA9IGlucHV0VGVuc29yLmRpbXM7XG4gIGxldCBuZXdPdXRwdXRTaGFwZSA9IG91dHB1dFNoYXBlO1xuICBjb25zdCB0cmFuc3Bvc2VBc1Jlc2hhcGUgPSBpbnB1dFJhbmsgPCAyIHx8IGlzVHJhbnNwb3NlUmVzaGFwZShwZXJtLCBpbnB1dFRlbnNvci5kaW1zKTtcbiAgbGV0IGdldFNoYWRlclNvdXJjZTtcbiAgaWYgKHRyYW5zcG9zZUFzUmVzaGFwZSkge1xuICAgIGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgICAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGlucHV0RGF0YVR5cGUsIG5ld0lucHV0U2hhcGUsIDQpO1xuICAgICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0RGF0YVR5cGUsIG5ld091dHB1dFNoYXBlLCA0KTtcbiAgICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0X3NpemUnLCAndTMyJykuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgb3V0cHV0KX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cbiAgICBvdXRwdXRbZ2xvYmFsX2lkeF0gPSBpbnB1dFtnbG9iYWxfaWR4XTtcbiAgfWA7XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAnVHJhbnNwb3NlQ29weScsXG4gICAgICBzaGFkZXJDYWNoZTogeyBpbnB1dERlcGVuZGVuY2llczogWyd0eXBlJ10gfSxcbiAgICAgIGdldFJ1bkRhdGE6ICgpID0+IHtcbiAgICAgICAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0VGVuc29yLmRhdGFUeXBlIH1dLFxuICAgICAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLyAvIDQgLyogY29tcG9uZW50cyAqLykgfSxcbiAgICAgICAgICBwcm9ncmFtVW5pZm9ybXM6IFt7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA0KSB9XSxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgfTtcbiAgfVxuICBjb25zdCB7IG5ld1NoYXBlLCBuZXdQZXJtIH0gPSBzcXVlZXplU2hhcGUoaW5wdXRUZW5zb3IuZGltcywgcGVybSk7XG4gIGNvbnN0IGNoYW5uZWxzTGFzdCA9IFNoYXBlVXRpbC5hcmVFcXVhbChuZXdQZXJtLCBbMiwgMywgMV0pO1xuICBjb25zdCBjaGFubmVsc0ZpcnN0ID0gU2hhcGVVdGlsLmFyZUVxdWFsKG5ld1Blcm0sIFszLCAxLCAyXSk7XG4gIGNvbnN0IHVzZVNoYXJlZCA9IG5ld1NoYXBlLmxlbmd0aCA9PT0gMiB8fCBjaGFubmVsc0xhc3QgfHwgY2hhbm5lbHNGaXJzdDtcbiAgaWYgKHVzZVNoYXJlZCkge1xuICAgIG5ld0lucHV0U2hhcGUgPSBjaGFubmVsc0xhc3RcbiAgICAgID8gW25ld1NoYXBlWzBdLCBuZXdTaGFwZVsxXSAqIG5ld1NoYXBlWzJdXVxuICAgICAgOiBjaGFubmVsc0ZpcnN0XG4gICAgICAgID8gW25ld1NoYXBlWzBdICogbmV3U2hhcGVbMV0sIG5ld1NoYXBlWzJdXVxuICAgICAgICA6IG5ld1NoYXBlO1xuICAgIG5ld091dHB1dFNoYXBlID0gW25ld0lucHV0U2hhcGVbMV0sIG5ld0lucHV0U2hhcGVbMF1dO1xuICAgIGNvbnN0IHRpbGVTaXplID0gMTY7XG4gICAgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ2EnLCBpbnB1dERhdGFUeXBlLCBuZXdJbnB1dFNoYXBlLmxlbmd0aCk7XG4gICAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXREYXRhVHlwZSwgbmV3T3V0cHV0U2hhcGUubGVuZ3RoKTtcbiAgICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0X3NpemUnLCAndTMyJykuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgb3V0cHV0KX1cbiAgdmFyPHdvcmtncm91cD4gdGlsZSA6IGFycmF5PGFycmF5PCR7b3V0cHV0LnR5cGUudmFsdWV9LCAke3RpbGVTaXplICsgMX0+LCAke3RpbGVTaXplfT47XG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydChbdGlsZVNpemUsIHRpbGVTaXplLCAxXSl9XG4gICAgbGV0IHN0cmlkZSA9ICh1bmlmb3Jtcy5vdXRwdXRfc2hhcGVbMV0gLSAxKSAvICR7dGlsZVNpemV9ICsgMTtcbiAgICBsZXQgd29ya2dyb3VwX2lkX3ggPSB3b3JrZ3JvdXBfaW5kZXggJSBzdHJpZGU7XG4gICAgbGV0IHdvcmtncm91cF9pZF95ID0gd29ya2dyb3VwX2luZGV4IC8gc3RyaWRlO1xuICAgIGxldCBpbnB1dF9jb2wgPSB3b3JrZ3JvdXBfaWRfeSAqICR7dGlsZVNpemV9dSArIGxvY2FsX2lkLng7XG4gICAgbGV0IGlucHV0X3JvdyA9IHdvcmtncm91cF9pZF94ICogJHt0aWxlU2l6ZX11ICsgbG9jYWxfaWQueTtcbiAgICBpZiAoaW5wdXRfcm93IDwgdW5pZm9ybXMuYV9zaGFwZVswXSAmJiBpbnB1dF9jb2wgPCB1bmlmb3Jtcy5hX3NoYXBlWzFdKSB7XG4gICAgICB0aWxlW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdID0gJHtpbnB1dC5nZXRCeUluZGljZXMoYCR7aW5wdXQudHlwZS5pbmRpY2VzfShpbnB1dF9yb3csIGlucHV0X2NvbClgKX07XG4gICAgfVxuICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgIGxldCBvdXRwdXRfY29sID0gd29ya2dyb3VwX2lkX3ggKiAke3RpbGVTaXplfXUgKyBsb2NhbF9pZC54O1xuICAgIGxldCBvdXRwdXRfcm93ID0gd29ya2dyb3VwX2lkX3kgKiAke3RpbGVTaXplfXUgKyBsb2NhbF9pZC55O1xuICAgIGlmIChvdXRwdXRfcm93IDwgdW5pZm9ybXMub3V0cHV0X3NoYXBlWzBdICYmIG91dHB1dF9jb2wgPCB1bmlmb3Jtcy5vdXRwdXRfc2hhcGVbMV0pIHtcbiAgICAgICR7b3V0cHV0LnNldEJ5SW5kaWNlcyhgJHtvdXRwdXQudHlwZS5pbmRpY2VzfShvdXRwdXRfcm93LCBvdXRwdXRfY29sKWAsICd0aWxlW2xvY2FsX2lkLnhdW2xvY2FsX2lkLnldJyl9XG4gICAgfVxuICB9YDtcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAnVHJhbnNwb3NlU2hhcmVkJyxcbiAgICAgIHNoYWRlckNhY2hlOiB7IGlucHV0RGVwZW5kZW5jaWVzOiBbJ3R5cGUnXSB9LFxuICAgICAgZ2V0UnVuRGF0YTogKCkgPT4ge1xuICAgICAgICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRUZW5zb3IuZGF0YVR5cGUgfV0sXG4gICAgICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwobmV3T3V0cHV0U2hhcGVbMV0gLyB0aWxlU2l6ZSksIHk6IE1hdGguY2VpbChuZXdPdXRwdXRTaGFwZVswXSAvIHRpbGVTaXplKSB9LFxuICAgICAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICAgICAgICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG5ld0lucHV0U2hhcGUsIG5ld091dHB1dFNoYXBlKSxcbiAgICAgICAgICBdLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICB9O1xuICB9XG5cbiAgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdhJywgaW5wdXREYXRhVHlwZSwgbmV3SW5wdXRTaGFwZS5sZW5ndGgpO1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dERhdGFUeXBlLCBuZXdPdXRwdXRTaGFwZS5sZW5ndGgpO1xuICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0X3NpemUnLCAndTMyJykuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgb3V0cHV0KX1cblxuICAke3Blcm1GdW5jdGlvbkJvZHkocGVybSwgaW5wdXRSYW5rLCBpbnB1dCwgb3V0cHV0KX1cblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuXG4gICAgbGV0IGluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgbGV0IGFJbmRpY2VzID0gcGVybShpbmRpY2VzKTtcblxuICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgaW5wdXQuZ2V0QnlJbmRpY2VzKCdhSW5kaWNlcycpKX1cbiAgfWA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ1RyYW5zcG9zZScsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7cGVybUF0dHJ9YCwgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuayddIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4ge1xuICAgICAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRUZW5zb3IuZGF0YVR5cGUgfV0sXG4gICAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgICAgcHJvZ3JhbVVuaWZvcm1zOiBbXG4gICAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICAgICAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhuZXdJbnB1dFNoYXBlLCBuZXdPdXRwdXRTaGFwZSksXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHRyYW5zcG9zZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogVHJhbnNwb3NlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcy5wZXJtKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCBhdHRyaWJ1dGVzLnBlcm0pKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZVRyYW5zcG9zZUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBUcmFuc3Bvc2VBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IHBlcm06IGF0dHJpYnV0ZXMucGVybSBhcyBudW1iZXJbXSB9KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5pbXBvcnQgeyBjcmVhdGVSZWR1Y2VBdHRyaWJ1dGVzRnJvbUlucHV0cywgUmVkdWNlQXR0cmlidXRlcyB9IGZyb20gJy4vcmVkdWNlJztcbmltcG9ydCB7IGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvIH0gZnJvbSAnLi90cmFuc3Bvc2UnO1xuXG5jb25zdCByZWR1Y2VPcHM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gIG1heDogJ3NlbGVjdChiZXN0VmFsdWUsIGNhbmRpZGF0ZSwgY2FuZGlkYXRlID4gYmVzdFZhbHVlKScsXG4gIG1pbjogJ3NlbGVjdChiZXN0VmFsdWUsIGNhbmRpZGF0ZSwgY2FuZGlkYXRlIDwgYmVzdFZhbHVlKScsXG4gIG1lYW46ICdiZXN0VmFsdWUgKyBjYW5kaWRhdGUnLFxuICBzdW06ICdiZXN0VmFsdWUgKyBjYW5kaWRhdGUnLFxuICBwcm9kOiAnYmVzdFZhbHVlICogY2FuZGlkYXRlJyxcbiAgc3VtU3F1YXJlOiAnYmVzdFZhbHVlICsgY2FuZGlkYXRlICogY2FuZGlkYXRlJyxcbiAgbG9nU3VtRXhwOiAnYmVzdFZhbHVlICsgZXhwKGNhbmRpZGF0ZSknLFxuICBsMTogJ2Jlc3RWYWx1ZSArIGFicyhjYW5kaWRhdGUpJyxcbiAgbDI6ICdiZXN0VmFsdWUgKyBjYW5kaWRhdGUgKiBjYW5kaWRhdGUnLFxuICBsb2dTdW06ICdiZXN0VmFsdWUgKyBjYW5kaWRhdGUnLFxufTtcblxuY29uc3QgcmVkdWNlU2hhcmVkT3BzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICBtYXg6ICdzZWxlY3QoYmVzdFZhbHVlLCBjYW5kaWRhdGUsIGNhbmRpZGF0ZSA+IGJlc3RWYWx1ZSknLFxuICBtaW46ICdzZWxlY3QoYmVzdFZhbHVlLCBjYW5kaWRhdGUsIGNhbmRpZGF0ZSA8IGJlc3RWYWx1ZSknLFxuICBtZWFuOiAnYmVzdFZhbHVlICsgY2FuZGlkYXRlJyxcbiAgc3VtOiAnYmVzdFZhbHVlICsgY2FuZGlkYXRlJyxcbiAgcHJvZDogJ2Jlc3RWYWx1ZSAqIGNhbmRpZGF0ZScsXG4gIHN1bVNxdWFyZTogJ2Jlc3RWYWx1ZSArIGNhbmRpZGF0ZScsXG4gIGxvZ1N1bUV4cDogJ2Jlc3RWYWx1ZSArIGNhbmRpZGF0ZScsXG4gIGwxOiAnYmVzdFZhbHVlICsgY2FuZGlkYXRlJyxcbiAgbDI6ICdiZXN0VmFsdWUgKyBjYW5kaWRhdGUnLFxuICBsb2dTdW06ICdiZXN0VmFsdWUgKyBjYW5kaWRhdGUnLFxufTtcblxuY29uc3QgcmVkdWNlSW5pdFZhbHVlczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHtcbiAgbWF4OiAnX0Fbb2Zmc2V0XScsXG4gIG1pbjogJ19BW29mZnNldF0nLFxuICBtZWFuOiAnMCcsXG4gIHN1bTogJzAnLFxuICBwcm9kOiAnMScsXG4gIHN1bVNxdWFyZTogJzAnLFxuICBsb2dTdW1FeHA6ICcwJyxcbiAgbDE6ICcwJyxcbiAgbDI6ICcwJyxcbiAgbG9nU3VtOiAnMCcsXG59O1xuXG5jb25zdCByZWR1Y2VPdXRwdXRWYWx1ZXM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gIG1heDogJ2Jlc3RWYWx1ZScsXG4gIG1pbjogJ2Jlc3RWYWx1ZScsXG4gIHN1bTogJ2Jlc3RWYWx1ZScsXG4gIHByb2Q6ICdiZXN0VmFsdWUnLFxuICBzdW1TcXVhcmU6ICdiZXN0VmFsdWUnLFxuICBsb2dTdW1FeHA6ICdsb2coYmVzdFZhbHVlKScsXG4gIGwxOiAnYmVzdFZhbHVlJyxcbiAgbDI6ICdzcXJ0KGJlc3RWYWx1ZSknLFxuICBsb2dTdW06ICdsb2coYmVzdFZhbHVlKScsXG59O1xuXG5jb25zdCBnZXRJbm5lck1vc3RBeGVzID0gKG51bUlubmVyQXhlczogbnVtYmVyLCByYW5rOiBudW1iZXIpOiBudW1iZXJbXSA9PiB7XG4gIGNvbnN0IHJlcyA9IFtdO1xuICBmb3IgKGxldCBpID0gcmFuayAtIG51bUlubmVyQXhlczsgaSA8IHJhbms7ICsraSkge1xuICAgIHJlcy5wdXNoKGkpO1xuICB9XG4gIHJldHVybiByZXM7XG59O1xuXG5jb25zdCBjb21wdXRlT3V0QW5kUmVkdWNlU2hhcGVzID0gKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgYXhlczogcmVhZG9ubHkgbnVtYmVyW10pOiBbbnVtYmVyW10sIG51bWJlcltdXSA9PiB7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gW107XG4gIGNvbnN0IHJhbmsgPSBzaGFwZS5sZW5ndGg7XG4gIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IHJhbms7IGRpbSsrKSB7XG4gICAgaWYgKGF4ZXMuaW5kZXhPZihkaW0pID09PSAtMSkge1xuICAgICAgb3V0cHV0U2hhcGUucHVzaChzaGFwZVtkaW1dKTtcbiAgICB9XG4gIH1cbiAgY29uc3QgcmVkdWNlU2hhcGUgPSBheGVzLm1hcCgoZGltKSA9PiBzaGFwZVtkaW1dKTtcbiAgcmV0dXJuIFtvdXRwdXRTaGFwZSwgcmVkdWNlU2hhcGVdO1xufTtcblxuY29uc3QgZXhwYW5kU2hhcGVUb0tlZXBEaW0gPSAoc2hhcGU6IG51bWJlcltdLCBheGVzOiBudW1iZXJbXSk6IG51bWJlcltdID0+IHtcbiAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aCArIGF4ZXMubGVuZ3RoO1xuICBjb25zdCBleHBhbmRTaGFwZSA9IFtdO1xuICBsZXQgc2hhcGVJZHggPSAwO1xuICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCByYW5rOyBkaW0rKykge1xuICAgIGlmIChheGVzLmluZGV4T2YoZGltKSA9PT0gLTEpIHtcbiAgICAgIGV4cGFuZFNoYXBlLnB1c2goc2hhcGVbc2hhcGVJZHgrK10pO1xuICAgIH0gZWxzZSB7XG4gICAgICBleHBhbmRTaGFwZS5wdXNoKDEpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZXhwYW5kU2hhcGU7XG59O1xuXG5jb25zdCBhcmVBeGVzSW5uZXJNb3N0RGltcyA9IChheGVzOiBudW1iZXJbXSwgcmFuazogbnVtYmVyKTogYm9vbGVhbiA9PiB7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYXhlcy5sZW5ndGg7ICsraSkge1xuICAgIGlmIChheGVzW2F4ZXMubGVuZ3RoIC0gaSAtIDFdICE9PSByYW5rIC0gMSAtIGkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5jb25zdCBnZXRBeGVzUGVybXV0YXRpb24gPSAoYXhlczogbnVtYmVyW10sIHJhbms6IG51bWJlcik6IG51bWJlcltdID0+IHtcbiAgY29uc3QgcmVzID0gW107XG4gIGlmICghYXJlQXhlc0lubmVyTW9zdERpbXMoYXhlcywgcmFuaykpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbms7ICsraSkge1xuICAgICAgaWYgKGF4ZXMuaW5kZXhPZihpKSA9PT0gLTEpIHtcbiAgICAgICAgcmVzLnB1c2goaSk7XG4gICAgICB9XG4gICAgfVxuICAgIGF4ZXMuZm9yRWFjaCgoYXhpcykgPT4gcmVzLnB1c2goYXhpcykpO1xuICB9XG4gIHJldHVybiByZXM7XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlUmVkdWNlU2hhcmVkUHJvZ3JhbUluZm8gPSAoXG4gIG5hbWU6IHN0cmluZyxcbiAgY2FjaGVLZXk6IHN0cmluZyxcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIHJlZHVjZVR5cGU6IHN0cmluZyxcbiAgb3V0cHV0RGF0YVR5cGU6IERhdGFUeXBlLFxuICBvdXRwdXRTaGFwZTogbnVtYmVyW10sXG4gIHJlZHVjZVNoYXBlOiBudW1iZXJbXSxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuXG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gIGNvbnN0IHJlZHVjZVNpemUgPSBTaGFwZVV0aWwuc2l6ZShyZWR1Y2VTaGFwZSk7XG5cbiAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdfQScsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRTaGFwZSk7XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBvdXRwdXREYXRhVHlwZSwgb3V0cHV0U2hhcGUpO1xuXG4gIGxldCB3b3JrZ3JvdXBTaXplID0gNjQ7XG4gIC8vIElmIG9ubHkgb25lIHdvcmtncm91cCBpcyBkaXNwYXRjaGVkLCBpbmNyZWFzZSB3b3JrZ3JvdXBTaXplIHRvIGltcHJvdmUgcGFyYWxsZWxpc20uXG4gIGlmIChvdXRwdXRTaXplID09PSAxKSB7XG4gICAgd29ya2dyb3VwU2l6ZSA9IDI1NjtcbiAgfVxuXG4gIGNvbnN0IHNoYXJlZE1lbW9yeVNuaXBwZXQgPSBgXG4gICAgICAgICAgdmFyPHdvcmtncm91cD4gYUJlc3RWYWx1ZXMgOiBhcnJheTxmMzIsICR7d29ya2dyb3VwU2l6ZX0+O1xuICAgICAgIGA7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gICAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybSgncmVkdWNlU2l6ZScsICd1MzInKS5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBvdXRwdXQpfVxuICAgICAgICAke3NoYXJlZE1lbW9yeVNuaXBwZXR9XG4gICAgICAgIGZuIERJVl9DRUlMKGEgOiB1MzIsIGIgOiB1MzIpIC0+IHUzMiB7XG4gICAgICAgICAgcmV0dXJuICgoYSAtIDF1KSAvIGIgKyAxdSk7XG4gICAgICAgICB9XG4gICAgICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQod29ya2dyb3VwU2l6ZSl9XG5cbiAgICAgICAgICBsZXQgb3V0cHV0SW5kZXggPSBnbG9iYWxfaWR4IC8gJHt3b3JrZ3JvdXBTaXplfTtcbiAgICAgICAgICBsZXQgb2Zmc2V0ID0gb3V0cHV0SW5kZXggKiB1bmlmb3Jtcy5yZWR1Y2VTaXplO1xuXG4gICAgICAgICAgdmFyIGJlc3RWYWx1ZSA9IGYzMigke3JlZHVjZUluaXRWYWx1ZXNbcmVkdWNlVHlwZV19KTtcbiAgICAgICAgICBsZXQgTGVuZ3RoID0gdW5pZm9ybXMucmVkdWNlU2l6ZTtcbiAgICAgICAgICBmb3IgKHZhciBrID0gbG9jYWxfaWR4OyBrIDwgTGVuZ3RoOyBrID0gayArICR7d29ya2dyb3VwU2l6ZX0pIHtcbiAgICAgICAgICAgbGV0IGNhbmRpZGF0ZSA9IGYzMigke2lucHV0LmdldEJ5T2Zmc2V0KCdvZmZzZXQgKyBrJyl9KTtcbiAgICAgICAgICAgYmVzdFZhbHVlID0gJHtyZWR1Y2VPcHNbcmVkdWNlVHlwZV19O1xuICAgICAgICAgIH1cbiAgICAgICAgICBhQmVzdFZhbHVlc1tsb2NhbF9pZHhdID0gYmVzdFZhbHVlO1xuICAgICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgICAgdmFyIHJlZHVjZVNpemUgPSBtaW4oTGVuZ3RoLCAke3dvcmtncm91cFNpemV9dSk7XG4gICAgICAgICBmb3IgKHZhciBjdXJyZW50U2l6ZSA9IHJlZHVjZVNpemUgLyAydTsgcmVkdWNlU2l6ZSA+IDF1O1xuICAgICAgICAgICAgIGN1cnJlbnRTaXplID0gcmVkdWNlU2l6ZSAvIDJ1KSB7XG4gICAgICAgICAgIGxldCBpbnRlcnZhbCA9IERJVl9DRUlMKHJlZHVjZVNpemUsIDJ1KTtcbiAgICAgICAgICAgaWYgKGxvY2FsX2lkeCA8IGN1cnJlbnRTaXplKSB7XG4gICAgICAgICAgICBsZXQgY2FuZGlkYXRlID0gYUJlc3RWYWx1ZXNbbG9jYWxfaWR4ICsgaW50ZXJ2YWxdO1xuICAgICAgICAgICAgYmVzdFZhbHVlID0gJHtyZWR1Y2VTaGFyZWRPcHNbcmVkdWNlVHlwZV19O1xuICAgICAgICAgICAgYUJlc3RWYWx1ZXNbbG9jYWxfaWR4XSA9IGJlc3RWYWx1ZTtcbiAgICAgICAgICAgfVxuICAgICAgICAgICByZWR1Y2VTaXplID0gaW50ZXJ2YWw7XG4gICAgICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcbiAgICAgICAgIH1cblxuICAgICAgICAgaWYgKGxvY2FsX2lkeCA9PSAwdSkge1xuICAgICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KFxuICAgICAgICAgICAgJ291dHB1dEluZGV4JyxcbiAgICAgICAgICAgIGAke1xuICAgICAgICAgICAgICByZWR1Y2VUeXBlID09PSAnbWVhbidcbiAgICAgICAgICAgICAgICA/IGAke291dHB1dC50eXBlLnN0b3JhZ2V9KGJlc3RWYWx1ZSAvIGYzMih1bmlmb3Jtcy5yZWR1Y2VTaXplKSlgXG4gICAgICAgICAgICAgICAgOiBgJHtvdXRwdXQudHlwZS5zdG9yYWdlfSgke3JlZHVjZU91dHB1dFZhbHVlc1tyZWR1Y2VUeXBlXX0pYFxuICAgICAgICAgICAgfWAsXG4gICAgICAgICAgKX07XG4gICAgICAgICB9XG4gICAgICAgIH1gO1xuXG4gIC8vIE9uZSB3b3JrIGdyb3VwIGlzIHJlc3BvbnNpYmxlIGZvciBvbmx5IG9uZSBlbGVtZW50IG9mIG91dHB1dC5cbiAgcmV0dXJuIHtcbiAgICBuYW1lLFxuICAgIC8vIE5vdGUgdGhhdCBpbiBKU0VQLCBXRyBzaXplIGlzIG5vdCBpbmNsdWRlZCBpbiBjYWNoZSBieSBkZWZhdWx0LCBidXQgV2ViR1BVIEVQIGl0IGlzLlxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2NhY2hlS2V5fTske3dvcmtncm91cFNpemV9YCwgaW5wdXREZXBlbmRlbmNpZXM6IFsndHlwZSddIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IG91dHB1dERhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBvdXRwdXRTaXplIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXM6IFt7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcmVkdWNlU2l6ZSB9XSxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmNvbnN0IHJlZHVjZUNvbW1vbiA9IChcbiAgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsXG4gIG5hbWU6IHN0cmluZyxcbiAgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyxcbiAgcmVkdWNlVHlwZTogJ3N1bScgfCAnc3VtU3F1YXJlJyB8ICdwcm9kJyB8ICdtaW4nIHwgJ21heCcgfCAnbWVhbicgfCAnbG9nU3VtRXhwJyB8ICdsMScgfCAnbDInIHwgJ2xvZ1N1bScsXG4pOiB2b2lkID0+IHtcbiAgY29uc3QgdXBkYXRlZEF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMgPVxuICAgIGNvbnRleHQuaW5wdXRzLmxlbmd0aCA9PT0gMSA/IGF0dHJpYnV0ZXMgOiBjcmVhdGVSZWR1Y2VBdHRyaWJ1dGVzRnJvbUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG5cbiAgbGV0IHVwZGF0ZWRBeGVzID0gdXBkYXRlZEF0dHJpYnV0ZXMuYXhlcztcbiAgaWYgKHVwZGF0ZWRBeGVzLmxlbmd0aCA9PT0gMCAmJiAhdXBkYXRlZEF0dHJpYnV0ZXMubm9vcFdpdGhFbXB0eUF4ZXMpIHtcbiAgICB1cGRhdGVkQXhlcyA9IGNvbnRleHQuaW5wdXRzWzBdLmRpbXMubWFwKChfZGltLCBpKSA9PiBpKTtcbiAgfVxuICBjb25zdCBub3JtYWxpemVBeGVzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4ZXModXBkYXRlZEF4ZXMsIGNvbnRleHQuaW5wdXRzWzBdLmRpbXMubGVuZ3RoKTtcblxuICBsZXQgYXhlcyA9IG5vcm1hbGl6ZUF4ZXM7XG4gIGxldCBpbnB1dCA9IGNvbnRleHQuaW5wdXRzWzBdO1xuICBjb25zdCBwZXJtdXRlZEF4ZXMgPSBnZXRBeGVzUGVybXV0YXRpb24oYXhlcywgY29udGV4dC5pbnB1dHNbMF0uZGltcy5sZW5ndGgpO1xuICBpZiAocGVybXV0ZWRBeGVzLmxlbmd0aCA+IDApIHtcbiAgICBpbnB1dCA9IGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgcGVybXV0ZWRBeGVzKSwge1xuICAgICAgaW5wdXRzOiBbMF0sXG4gICAgICBvdXRwdXRzOiBbLTFdLFxuICAgIH0pWzBdO1xuICAgIGF4ZXMgPSBnZXRJbm5lck1vc3RBeGVzKGF4ZXMubGVuZ3RoLCBpbnB1dC5kaW1zLmxlbmd0aCk7XG4gIH1cblxuICBjb25zdCBbb3V0cHV0U2hhcGUsIHJlZHVjZVNoYXBlXSA9IGNvbXB1dGVPdXRBbmRSZWR1Y2VTaGFwZXMoaW5wdXQuZGltcywgYXhlcyk7XG4gIGxldCBmaW5hbE91dHB1dFNoYXBlID0gb3V0cHV0U2hhcGU7XG4gIGlmICh1cGRhdGVkQXR0cmlidXRlcy5rZWVwRGltcykge1xuICAgIGZpbmFsT3V0cHV0U2hhcGUgPSBleHBhbmRTaGFwZVRvS2VlcERpbShvdXRwdXRTaGFwZSwgbm9ybWFsaXplQXhlcyk7XG4gIH1cblxuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlUmVkdWNlU2hhcmVkUHJvZ3JhbUluZm8oXG4gICAgICBuYW1lLFxuICAgICAgdXBkYXRlZEF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgICBbaW5wdXRdLFxuICAgICAgcmVkdWNlVHlwZSxcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlLFxuICAgICAgZmluYWxPdXRwdXRTaGFwZSxcbiAgICAgIHJlZHVjZVNoYXBlLFxuICAgICksXG4gICAgeyBpbnB1dHM6IFtpbnB1dF0gfSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VNZWFuU2hhcmVkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHJlZHVjZUNvbW1vbihjb250ZXh0LCAnUmVkdWNlTWVhblNoYXJlZCcsIGF0dHJpYnV0ZXMsICdtZWFuJyk7XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTDFTaGFyZWQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgcmVkdWNlQ29tbW9uKGNvbnRleHQsICdSZWR1Y2VMMVNoYXJlZCcsIGF0dHJpYnV0ZXMsICdsMScpO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlZHVjZUwyU2hhcmVkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHJlZHVjZUNvbW1vbihjb250ZXh0LCAnUmVkdWNlTDJTaGFyZWQnLCBhdHRyaWJ1dGVzLCAnbDInKTtcbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VMb2dTdW1FeHBTaGFyZWQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgcmVkdWNlQ29tbW9uKGNvbnRleHQsICdSZWR1Y2VMb2dTdW1FeHBTaGFyZWQnLCBhdHRyaWJ1dGVzLCAnbG9nU3VtRXhwJyk7XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTWF4U2hhcmVkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHJlZHVjZUNvbW1vbihjb250ZXh0LCAnUmVkdWNlTWF4U2hhcmVkJywgYXR0cmlidXRlcywgJ21heCcpO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlZHVjZU1pblNoYXJlZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICByZWR1Y2VDb21tb24oY29udGV4dCwgJ1JlZHVjZU1pblNoYXJlZCcsIGF0dHJpYnV0ZXMsICdtaW4nKTtcbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VQcm9kU2hhcmVkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHJlZHVjZUNvbW1vbihjb250ZXh0LCAnUmVkdWNlUHJvZFNoYXJlZCcsIGF0dHJpYnV0ZXMsICdwcm9kJyk7XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlU3VtU2hhcmVkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHJlZHVjZUNvbW1vbihjb250ZXh0LCAnUmVkdWNlU3VtU2hhcmVkJywgYXR0cmlidXRlcywgJ3N1bScpO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlZHVjZVN1bVNxdWFyZVNoYXJlZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICByZWR1Y2VDb21tb24oY29udGV4dCwgJ1JlZHVjZVN1bVNxdWFyZVNoYXJlZCcsIGF0dHJpYnV0ZXMsICdzdW1TcXVhcmUnKTtcbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VMb2dTdW1TaGFyZWQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgcmVkdWNlQ29tbW9uKGNvbnRleHQsICdSZWR1Y2VMb2dTdW1TaGFyZWQnLCBhdHRyaWJ1dGVzLCAnbG9nU3VtJyk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbVNoYWRlckNhY2hlSW5mbyB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsIEluZGljZXNIZWxwZXIsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5pbXBvcnQge1xuICByZWR1Y2VMMVNoYXJlZCxcbiAgcmVkdWNlTDJTaGFyZWQsXG4gIHJlZHVjZUxvZ1N1bUV4cFNoYXJlZCxcbiAgcmVkdWNlTG9nU3VtU2hhcmVkLFxuICByZWR1Y2VNYXhTaGFyZWQsXG4gIHJlZHVjZU1lYW5TaGFyZWQsXG4gIHJlZHVjZU1pblNoYXJlZCxcbiAgcmVkdWNlUHJvZFNoYXJlZCxcbiAgcmVkdWNlU3VtU2hhcmVkLFxuICByZWR1Y2VTdW1TcXVhcmVTaGFyZWQsXG59IGZyb20gJy4vcmVkdWNlLXNoYXJlZCc7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggPT09IDAgfHwgaW5wdXRzLmxlbmd0aCA+IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlZHVjZSBvcCByZXF1aXJlcyAxIG9yIDIgaW5wdXRzLicpO1xuICB9XG5cbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDIgJiYgaW5wdXRzWzFdLmRpbXMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGF4ZXMgaW5wdXQgZGltcy4nKTtcbiAgfVxufTtcblxuZXhwb3J0IGludGVyZmFjZSBSZWR1Y2VBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAga2VlcERpbXM6IGJvb2xlYW47XG4gIG5vb3BXaXRoRW1wdHlBeGVzOiBib29sZWFuO1xuICBheGVzOiBudW1iZXJbXTtcbn1cblxuZXhwb3J0IHR5cGUgUmVkdWNlT3AgPSAoXG4gIGlucHV0OiBJbmRpY2VzSGVscGVyLFxuICBvdXRwdXQ6IEluZGljZXNIZWxwZXIsXG4gIGF4ZXM6IHJlYWRvbmx5IG51bWJlcltdLFxuKSA9PiBbc3RyaW5nLCBzdHJpbmcsIHN0cmluZywgc3RyaW5nLCAuLi5zdHJpbmdbXV07XG5cbmNvbnN0IG5vT3A6IFJlZHVjZU9wID0gKGlucHV0KSA9PiBbJycsICcnLCBgdmFyIHZhbHVlID0gJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX07YCwgJyddO1xuZXhwb3J0IGNvbnN0IGNyZWF0ZVJlZHVjZVByb2dyYW1JbmZvID0gKFxuICBuYW1lOiBzdHJpbmcsXG4gIHNoYWRlckNhY2hlOiBQcm9ncmFtU2hhZGVyQ2FjaGVJbmZvLFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgcmVkdWNlT3A6IFJlZHVjZU9wLFxuICBheGVzSW5wdXQ6IG51bWJlcltdLFxuICBvdXRwdXREYXRhVHlwZTogRGF0YVR5cGUsXG4gIGtlZXBEaW1zID0gZmFsc2UsXG4gIG5vb3BXaXRoRW1wdHlBeGVzID0gZmFsc2UsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IG91dHB1dFNoYXBlOiBudW1iZXJbXSA9IFtdO1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGlucHV0UmFuayA9IGlucHV0U2hhcGUubGVuZ3RoO1xuICBjb25zdCBheGVzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4ZXMoYXhlc0lucHV0LCBpbnB1dFJhbmspO1xuICBjb25zdCByZWR1Y2VPbkFsbEF4ZXMgPSAhbm9vcFdpdGhFbXB0eUF4ZXMgJiYgYXhlcy5sZW5ndGggPT09IDA7XG4gIGlucHV0U2hhcGUuZm9yRWFjaCgoZCwgaSkgPT4ge1xuICAgIGlmIChyZWR1Y2VPbkFsbEF4ZXMgfHwgYXhlcy5pbmRleE9mKGkpID49IDApIHtcbiAgICAgIGlmIChrZWVwRGltcykge1xuICAgICAgICBvdXRwdXRTaGFwZS5wdXNoKDEpO1xuICAgICAgfSAvLyBlbHNlIHsgLy8gc2tpcCB0aGlzIGF4aXN9XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dHB1dFNoYXBlLnB1c2goZCk7XG4gICAgfVxuICB9KTtcbiAgY29uc3Qgb3V0cHV0UmFuayA9IG91dHB1dFNoYXBlLmxlbmd0aDtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgaWR4Q29weTogc3RyaW5nW10gPSBbXTsgLy8gY29weSBvdXRwdXQgaW5kZXhlcyB0byBpbnB1dCBpbmRleGVzXG5cbiAgICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ19BJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dFJhbmspO1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBvdXRwdXREYXRhVHlwZSwgb3V0cHV0UmFuayk7XG4gICAgY29uc3Qgb3BzID0gcmVkdWNlT3AoaW5wdXQsIG91dHB1dCwgYXhlcyk7XG4gICAgbGV0IHJlZHVjZU9wcyA9IG9wc1syXTtcblxuICAgIGZvciAobGV0IGsgPSAwLCBsID0gMDsgayA8IGlucHV0UmFuazsgaysrKSB7XG4gICAgICAvLyBpZiB0aGlzIGF4aXMgaXMgcmVkdWNlZFxuICAgICAgaWYgKHJlZHVjZU9uQWxsQXhlcyB8fCBheGVzLmluZGV4T2YoaykgPj0gMCkge1xuICAgICAgICBpZiAoa2VlcERpbXMpIHtcbiAgICAgICAgICBsKys7XG4gICAgICAgIH1cbiAgICAgICAgLy8gbG9vcCBvdmVyIHRoZSBkLXRoIGF4aXNcbiAgICAgICAgcmVkdWNlT3BzID0gYGZvcih2YXIgaiR7a306IHUzMiA9IDA7IGoke2t9IDwgJHtpbnB1dFNoYXBlW2tdfTsgaiR7a30rKykge1xuICAgICAgICAgICAgICAgICAgJHtvcHNbMl0uaW5jbHVkZXMoJ2xhc3RfaW5kZXgnKSA/IGBsZXQgbGFzdF9pbmRleCA9IGoke2t9O2AgOiAnJ31cbiAgICAgICAgICAgICAgICAgICR7aW5wdXQuaW5kaWNlc1NldCgnaW5wdXRfaW5kaWNlcycsIGssIGBqJHtrfWApfVxuICAgICAgICAgICAgICAgICAgJHtyZWR1Y2VPcHN9XG4gICAgICAgICAgICAgICAgfWA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZHhDb3B5LnB1c2goYCR7aW5wdXQuaW5kaWNlc1NldCgnaW5wdXRfaW5kaWNlcycsIGssIG91dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRfaW5kaWNlcycsIGwpKX07YCk7XG4gICAgICAgIGwrKztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGBcblxuICAgICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ291dHB1dF9zaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIG91dHB1dCl9XG5cbiAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cbiAgICAgICAgICB2YXIgaW5wdXRfaW5kaWNlczogJHtpbnB1dC50eXBlLmluZGljZXN9O1xuICAgICAgICAgIGxldCBvdXRwdXRfaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcblxuICAgICAgICAgICR7aWR4Q29weS5qb2luKCdcXG4nKX1cbiAgICAgICAgICAke29wc1swXX0gICAgICAgLy8gaW5pdCBvcHMgZm9yIHJlZHVjZSBtYXgvbWluXG4gICAgICAgICAgJHtvcHNbMV19XG4gICAgICAgICAgJHtyZWR1Y2VPcHN9XG4gICAgICAgICAgJHtvcHNbM119XG4gICAgICAgICAgJHtvcHMubGVuZ3RoID09PSA0ID8gb3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3ZhbHVlJykgOiBvcHMuc2xpY2UoNCkuam9pbignXFxuJyl9XG4gICAgICAgIH1gO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICBzaGFkZXJDYWNoZSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogb3V0cHV0RGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXM6IFtcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICAgICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRTaGFwZSwgb3V0cHV0U2hhcGUpLFxuICAgICAgXSxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVSZWR1Y2VBdHRyaWJ1dGVzRnJvbUlucHV0cyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMsXG4pOiBSZWR1Y2VBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgYXhlczogbnVtYmVyW10gPSBbXTtcbiAgaWYgKGlucHV0c1sxXS5kaW1zWzBdID4gMCkge1xuICAgIGlucHV0c1sxXS5nZXRCaWdJbnQ2NEFycmF5KCkuZm9yRWFjaCgodikgPT4gYXhlcy5wdXNoKE51bWJlcih2KSkpO1xuICB9XG4gIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe1xuICAgIGF4ZXMsXG4gICAga2VlcERpbXM6IGF0dHJpYnV0ZXMua2VlcERpbXMsXG4gICAgbm9vcFdpdGhFbXB0eUF4ZXM6IGF0dHJpYnV0ZXMubm9vcFdpdGhFbXB0eUF4ZXMsXG4gIH0pO1xufTtcblxuY29uc3QgcnVuUmVkdWNlUHJvZ3JhbSA9IChcbiAgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsXG4gIG5hbWU6IHN0cmluZyxcbiAgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyxcbiAgcmVkdWNlT3A6IFJlZHVjZU9wLFxuKTogdm9pZCA9PiB7XG4gIGNvbnN0IGlucHV0cyA9IGNvbnRleHQuaW5wdXRzO1xuICBjb25zdCB1cGRhdGVkQXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyA9XG4gICAgaW5wdXRzLmxlbmd0aCA9PT0gMSA/IGF0dHJpYnV0ZXMgOiBjcmVhdGVSZWR1Y2VBdHRyaWJ1dGVzRnJvbUlucHV0cyhpbnB1dHMsIGF0dHJpYnV0ZXMpO1xuXG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVSZWR1Y2VQcm9ncmFtSW5mbyhcbiAgICAgIG5hbWUsXG4gICAgICB7IGhpbnQ6IHVwZGF0ZWRBdHRyaWJ1dGVzLmNhY2hlS2V5LCBpbnB1dERlcGVuZGVuY2llczogWydyYW5rJ10gfSxcbiAgICAgIFtpbnB1dHNbMF1dLFxuICAgICAgdXBkYXRlZEF0dHJpYnV0ZXMubm9vcFdpdGhFbXB0eUF4ZXMgJiYgdXBkYXRlZEF0dHJpYnV0ZXMuYXhlcy5sZW5ndGggPT09IDAgPyBub09wIDogcmVkdWNlT3AsXG4gICAgICB1cGRhdGVkQXR0cmlidXRlcy5heGVzLFxuICAgICAgaW5wdXRzWzBdLmRhdGFUeXBlLFxuICAgICAgdXBkYXRlZEF0dHJpYnV0ZXMua2VlcERpbXMsXG4gICAgICB1cGRhdGVkQXR0cmlidXRlcy5ub29wV2l0aEVtcHR5QXhlcyxcbiAgICApLFxuICAgIHsgaW5wdXRzOiBbMF0gfSxcbiAgKTtcbn07XG5cbmNvbnN0IHJlZHVjZUxvZ1N1bU5haXZlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKGlucHV0LCBvdXRwdXQpID0+IFtcbiAgICBgdmFyIHZhbHVlID0gJHtvdXRwdXQudHlwZS5zdG9yYWdlfSgwKTtgLFxuICAgICcnLFxuICAgIGB2YWx1ZSArPSAke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfTtgLFxuICAgICd2YWx1ZSA9IGxvZyh2YWx1ZSk7JyxcbiAgXTtcbiAgcnVuUmVkdWNlUHJvZ3JhbShjb250ZXh0LCAnUmVkdWNlTG9nU3VtJywgYXR0cmlidXRlcywgcmVkdWNlT3ApO1xufTtcblxuY29uc3QgcmVkdWNlTDFOYWl2ZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnN0IHJlZHVjZU9wOiBSZWR1Y2VPcCA9IChpbnB1dCwgb3V0cHV0KSA9PiBbXG4gICAgYHZhciB2YWx1ZSA9ICR7b3V0cHV0LnR5cGUuc3RvcmFnZX0oMCk7YCxcbiAgICAnJyxcbiAgICBgdmFsdWUgKz0gYWJzKCR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9KTtgLFxuICAgICcnLFxuICBdO1xuICBydW5SZWR1Y2VQcm9ncmFtKGNvbnRleHQsICdSZWR1Y2VMMScsIGF0dHJpYnV0ZXMsIHJlZHVjZU9wKTtcbn07XG5cbmNvbnN0IHJlZHVjZUwyTmFpdmUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCByZWR1Y2VPcDogUmVkdWNlT3AgPSAoaW5wdXQsIG91dHB1dCkgPT4gW1xuICAgIGB2YXIgdCA9ICR7b3V0cHV0LnR5cGUudmFsdWV9KDApOyB2YXIgdmFsdWUgPSAke291dHB1dC50eXBlLnZhbHVlfSgwKTtgLFxuICAgICcnLFxuICAgIGB0ID0gJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX07IHZhbHVlICs9ICh0ICogdCk7YCxcbiAgICAndmFsdWUgPSBzcXJ0KHZhbHVlKTsnLFxuICBdO1xuICBydW5SZWR1Y2VQcm9ncmFtKGNvbnRleHQsICdSZWR1Y2VMMicsIGF0dHJpYnV0ZXMsIHJlZHVjZU9wKTtcbn07XG5cbmNvbnN0IHJlZHVjZUxvZ1N1bUV4cE5haXZlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKGlucHV0LCBvdXRwdXQpID0+IFtcbiAgICBgdmFyIHZhbHVlID0gJHtvdXRwdXQudHlwZS5zdG9yYWdlfSgwKTtgLFxuICAgICcnLFxuICAgIGB2YWx1ZSArPSBleHAoJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX0pO2AsXG4gICAgJ3ZhbHVlID0gbG9nKHZhbHVlKTsnLFxuICBdO1xuICBydW5SZWR1Y2VQcm9ncmFtKGNvbnRleHQsICdSZWR1Y2VMb2dTdW1FeHAnLCBhdHRyaWJ1dGVzLCByZWR1Y2VPcCk7XG59O1xuXG5jb25zdCByZWR1Y2VNYXhOYWl2ZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnN0IHJlZHVjZU9wOiBSZWR1Y2VPcCA9IChpbnB1dCwgX291dHB1dCwgYXhlcykgPT4ge1xuICAgIGNvbnN0IGlkeFplcm8gPSBbXTtcbiAgICBmb3IgKGxldCBrID0gMDsgayA8IGlucHV0LnJhbms7IGsrKykge1xuICAgICAgaWYgKGF4ZXMuaW5kZXhPZihrKSA+PSAwIHx8IGF4ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGlkeFplcm8ucHVzaChpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dF9pbmRpY2VzJywgaywgMCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBbXG4gICAgICBgJHtpZHhaZXJvLmpvaW4oJ1xcbicpfWAsXG4gICAgICBgdmFyIHZhbHVlID0gJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX07YCxcbiAgICAgIGB2YWx1ZSA9IG1heCh2YWx1ZSwgJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX0pO2AsXG4gICAgICAnJyxcbiAgICBdO1xuICB9O1xuICBydW5SZWR1Y2VQcm9ncmFtKGNvbnRleHQsICdSZWR1Y2VNYXgnLCBhdHRyaWJ1dGVzLCByZWR1Y2VPcCk7XG59O1xuXG5jb25zdCByZWR1Y2VNZWFuTmFpdmUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCByZWR1Y2VPcDogUmVkdWNlT3AgPSAoaW5wdXQsIG91dHB1dCwgYXhlcykgPT4ge1xuICAgIGxldCBzaXplID0gMS4wO1xuICAgIGZvciAobGV0IGsgPSAwOyBrIDwgaW5wdXQucmFuazsgaysrKSB7XG4gICAgICBpZiAoYXhlcy5pbmRleE9mKGspID49IDAgfHwgYXhlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgLy8gVE9ETzogdGhpcyBkZXBlbmRzIG9uIHRoZSBpbnB1dCBkaW1zLiBJZiB3ZSB3YW50IHRvIHVzZSB1bmlmb3JtLCB0aGlzIG5lZWQgdG8gYmUgdXBkYXRlZC5cbiAgICAgICAgc2l6ZSAqPSBjb250ZXh0LmlucHV0c1swXS5kaW1zW2tdO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBbXG4gICAgICAndmFyIHN1bSA9IGYzMigwKTsnLFxuICAgICAgJycsXG4gICAgICBgc3VtICs9IGYzMigke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfSk7YCxcbiAgICAgIGBsZXQgdmFsdWUgPSAke291dHB1dC50eXBlLnZhbHVlfShzdW0gLyAke3NpemV9KTtgLFxuICAgIF07XG4gIH07XG4gIHJ1blJlZHVjZVByb2dyYW0oY29udGV4dCwgJ1JlZHVjZU1lYW4nLCBhdHRyaWJ1dGVzLCByZWR1Y2VPcCk7XG59O1xuXG5jb25zdCByZWR1Y2VNaW5OYWl2ZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnN0IHJlZHVjZU9wOiBSZWR1Y2VPcCA9IChpbnB1dCwgX291dHB1dCwgYXhlcykgPT4ge1xuICAgIGNvbnN0IGlkeFplcm8gPSBbXTtcbiAgICBmb3IgKGxldCBrID0gMDsgayA8IGlucHV0LnJhbms7IGsrKykge1xuICAgICAgaWYgKGF4ZXMuaW5kZXhPZihrKSA+PSAwIHx8IGF4ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGlkeFplcm8ucHVzaChgaW5wdXRfaW5kaWNlc1ske2t9XSA9IDA7YCk7IC8vIGZpcnN0IGVsZW1lbnRcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gW1xuICAgICAgYCR7aWR4WmVyby5qb2luKCdcXG4nKX1gLFxuICAgICAgYHZhciB2YWx1ZSA9ICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9O2AsXG4gICAgICBgdmFsdWUgPSBtaW4odmFsdWUsICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9KTtgLFxuICAgICAgJycsXG4gICAgXTtcbiAgfTtcbiAgcnVuUmVkdWNlUHJvZ3JhbShjb250ZXh0LCAnUmVkdWNlTWluJywgYXR0cmlidXRlcywgcmVkdWNlT3ApO1xufTtcblxuY29uc3QgcmVkdWNlUHJvZE5haXZlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKGlucHV0LCBvdXRwdXQpID0+IFtcbiAgICBgdmFyIHZhbHVlID0gJHtvdXRwdXQudHlwZS5zdG9yYWdlfSgxKTtgLFxuICAgICcnLFxuICAgIGB2YWx1ZSAqPSAke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfTtgLFxuICAgICcnLFxuICBdO1xuICBydW5SZWR1Y2VQcm9ncmFtKGNvbnRleHQsICdSZWR1Y2VQcm9kJywgYXR0cmlidXRlcywgcmVkdWNlT3ApO1xufTtcblxuY29uc3QgcmVkdWNlU3VtTmFpdmUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCByZWR1Y2VPcDogUmVkdWNlT3AgPSAoaW5wdXQsIG91dHB1dCkgPT4gW1xuICAgIGB2YXIgdmFsdWUgPSAke291dHB1dC50eXBlLnN0b3JhZ2V9KDApO2AsXG4gICAgJycsXG4gICAgYHZhbHVlICs9ICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9O2AsXG4gICAgJycsXG4gIF07XG4gIHJ1blJlZHVjZVByb2dyYW0oY29udGV4dCwgJ1JlZHVjZVN1bScsIGF0dHJpYnV0ZXMsIHJlZHVjZU9wKTtcbn07XG5cbmNvbnN0IHJlZHVjZVN1bVNxdWFyZU5haXZlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKGlucHV0LCBvdXRwdXQpID0+IFtcbiAgICBgdmFyIHQgPSAke291dHB1dC50eXBlLnZhbHVlfSgwKTsgdmFyIHZhbHVlID0gJHtvdXRwdXQudHlwZS52YWx1ZX0oMCk7YCxcbiAgICAnJyxcbiAgICBgdCA9ICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9OyB2YWx1ZSArPSB0ICogdDtgLFxuICAgICcnLFxuICBdO1xuICBydW5SZWR1Y2VQcm9ncmFtKGNvbnRleHQsICdSZWR1Y2VTdW1TcXVhcmUnLCBhdHRyaWJ1dGVzLCByZWR1Y2VPcCk7XG59O1xuXG5jb25zdCB1c2VOYWl2ZVJlZHVjZU1ldGhvZCA9IChcbiAgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBheGVzOiByZWFkb25seSBudW1iZXJbXSxcbiAgbm9vcFdpdGhFbXB0eUF4ZXM6IGJvb2xlYW4sXG4pOiBib29sZWFuID0+IHtcbiAgaWYgKGF4ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIG5vb3BXaXRoRW1wdHlBeGVzO1xuICB9XG5cbiAgbGV0IG91dHB1dFNpemUgPSAxO1xuICBsZXQgcmVkdWNlU2l6ZSA9IDE7XG4gIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGF4ZXMubGVuZ3RoOyBkaW0rKykge1xuICAgIGlmIChheGVzLmluZGV4T2YoZGltKSA9PT0gLTEpIHtcbiAgICAgIG91dHB1dFNpemUgKj0gc2hhcGVbZGltXTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVkdWNlU2l6ZSAqPSBzaGFwZVtkaW1dO1xuICAgIH1cbiAgfVxuXG4gIC8vIFRoZSBjb25kaXRpb24gZGF0YSBpcyB2ZXJ5IHJvdWdoLCBhbHRob3VnaCBjb25zaWRlcmluZyB0aGUgY291bnQgb2YgRXhlY3V0aW9uIFVuaXQgKEVVKSwgdGhlIHBvdGVudGlhbFxuICAvLyB3b3JrIGdyb3VwcyBpbiBhIEVVIGFuZCB0aGUgY291bnRzIG9mIGxvb3BzIGluIHRoZSBuYWl2ZSBhbmQgc2hhcmVkIG1ldGhvZHMsIGFsc28gZG9pbmcgZXhwZXJpbWVudHNcbiAgLy8gb24gc29tZSBtYWNoaW5lcy5cbiAgcmV0dXJuIHJlZHVjZVNpemUgPCAzMiAmJiBvdXRwdXRTaXplID4gMTAyNDtcbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VNZWFuID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmICh1c2VOYWl2ZVJlZHVjZU1ldGhvZChjb250ZXh0LmlucHV0c1swXS5kaW1zLCBhdHRyaWJ1dGVzLmF4ZXMsIGF0dHJpYnV0ZXMubm9vcFdpdGhFbXB0eUF4ZXMpKSB7XG4gICAgcmVkdWNlTWVhbk5haXZlKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9IGVsc2Uge1xuICAgIHJlZHVjZU1lYW5TaGFyZWQoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VMMSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBpZiAodXNlTmFpdmVSZWR1Y2VNZXRob2QoY29udGV4dC5pbnB1dHNbMF0uZGltcywgYXR0cmlidXRlcy5heGVzLCBhdHRyaWJ1dGVzLm5vb3BXaXRoRW1wdHlBeGVzKSkge1xuICAgIHJlZHVjZUwxTmFpdmUoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH0gZWxzZSB7XG4gICAgcmVkdWNlTDFTaGFyZWQoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VMMiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBpZiAodXNlTmFpdmVSZWR1Y2VNZXRob2QoY29udGV4dC5pbnB1dHNbMF0uZGltcywgYXR0cmlidXRlcy5heGVzLCBhdHRyaWJ1dGVzLm5vb3BXaXRoRW1wdHlBeGVzKSkge1xuICAgIHJlZHVjZUwyTmFpdmUoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH0gZWxzZSB7XG4gICAgcmVkdWNlTDJTaGFyZWQoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VMb2dTdW1FeHAgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKHVzZU5haXZlUmVkdWNlTWV0aG9kKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMsIGF0dHJpYnV0ZXMuYXhlcywgYXR0cmlidXRlcy5ub29wV2l0aEVtcHR5QXhlcykpIHtcbiAgICByZWR1Y2VMb2dTdW1FeHBOYWl2ZShjb250ZXh0LCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIHtcbiAgICByZWR1Y2VMb2dTdW1FeHBTaGFyZWQoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VNYXggPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKHVzZU5haXZlUmVkdWNlTWV0aG9kKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMsIGF0dHJpYnV0ZXMuYXhlcywgYXR0cmlidXRlcy5ub29wV2l0aEVtcHR5QXhlcykpIHtcbiAgICByZWR1Y2VNYXhOYWl2ZShjb250ZXh0LCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIHtcbiAgICByZWR1Y2VNYXhTaGFyZWQoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VNaW4gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKHVzZU5haXZlUmVkdWNlTWV0aG9kKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMsIGF0dHJpYnV0ZXMuYXhlcywgYXR0cmlidXRlcy5ub29wV2l0aEVtcHR5QXhlcykpIHtcbiAgICByZWR1Y2VNaW5OYWl2ZShjb250ZXh0LCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIHtcbiAgICByZWR1Y2VNaW5TaGFyZWQoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VQcm9kID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmICh1c2VOYWl2ZVJlZHVjZU1ldGhvZChjb250ZXh0LmlucHV0c1swXS5kaW1zLCBhdHRyaWJ1dGVzLmF4ZXMsIGF0dHJpYnV0ZXMubm9vcFdpdGhFbXB0eUF4ZXMpKSB7XG4gICAgcmVkdWNlUHJvZE5haXZlKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9IGVsc2Uge1xuICAgIHJlZHVjZVByb2RTaGFyZWQoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VTdW0gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKHVzZU5haXZlUmVkdWNlTWV0aG9kKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMsIGF0dHJpYnV0ZXMuYXhlcywgYXR0cmlidXRlcy5ub29wV2l0aEVtcHR5QXhlcykpIHtcbiAgICByZWR1Y2VTdW1OYWl2ZShjb250ZXh0LCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIHtcbiAgICByZWR1Y2VTdW1TaGFyZWQoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VTdW1TcXVhcmUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKHVzZU5haXZlUmVkdWNlTWV0aG9kKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMsIGF0dHJpYnV0ZXMuYXhlcywgYXR0cmlidXRlcy5ub29wV2l0aEVtcHR5QXhlcykpIHtcbiAgICByZWR1Y2VTdW1TcXVhcmVOYWl2ZShjb250ZXh0LCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIHtcbiAgICByZWR1Y2VTdW1TcXVhcmVTaGFyZWQoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VMb2dTdW0gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKHVzZU5haXZlUmVkdWNlTWV0aG9kKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMsIGF0dHJpYnV0ZXMuYXhlcywgYXR0cmlidXRlcy5ub29wV2l0aEVtcHR5QXhlcykpIHtcbiAgICByZWR1Y2VMb2dTdW1OYWl2ZShjb250ZXh0LCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIHtcbiAgICByZWR1Y2VMb2dTdW1TaGFyZWQoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbi8vIFRPRE86IHRoaXMgaXMgdGhlIHNhbWUgbmFpdmUgaW1wbGVtZW50YXRpb24gd2UgdXNlIGZvciByZWR1Y2UgdGhhdCBoYXNcbi8vIHBlcmZvcm1hbmNlIGxpbWl0YXRpb25zIHdoZW4gdGhlIHJlZHVjZWQgYXhpcyBpcyBsb25nLiBOZWVkIHRvIGFkZFxuLy8gYSBvcHRpbWl6ZWQgY29kZXBhdGggZm9yIHRoaXMuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0IH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVSZWR1Y2VQcm9ncmFtSW5mbywgUmVkdWNlT3AgfSBmcm9tICcuL3JlZHVjZSc7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggPT09IDAgfHwgaW5wdXRzLmxlbmd0aCA+IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0FyZ01pbk1heE9wIG9wIHJlcXVpcmVzIDEgb3IgMiBpbnB1dHMuJyk7XG4gIH1cbiAgaWYgKGlucHV0c1swXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuZmxvYXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaW5wdXQgdHlwZS4nKTtcbiAgfVxufTtcblxuZXhwb3J0IGludGVyZmFjZSBBcmdNaW5NYXhBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAga2VlcERpbXM6IGJvb2xlYW47XG4gIGF4aXM6IG51bWJlcjtcbiAgc2VsZWN0TGFzdEluZGV4OiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBhcmdNaW4gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEFyZ01pbk1heEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCBhcmdNaW5NYXhPcDogUmVkdWNlT3AgPSAoaW5wdXQsIG91dHB1dCwgYXhlcykgPT4ge1xuICAgIGNvbnN0IGlkeFplcm8gPSBbXTtcbiAgICBmb3IgKGxldCBrID0gMDsgayA8IGlucHV0LnJhbms7IGsrKykge1xuICAgICAgaWYgKGF4ZXMuaW5kZXhPZihrKSA+PSAwIHx8IGF4ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGlkeFplcm8ucHVzaChgaW5wdXRfaW5kaWNlc1ske2t9XSA9IDA7YCk7IC8vIGZpcnN0IGVsZW1lbnRcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFtcbiAgICAgIGAke2lkeFplcm8uam9pbignXFxuJyl9YCxcbiAgICAgIGB2YXIgdmFsdWUgPSAke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfTtcXG52YXIgYmVzdF9pbmRleCA6IGkzMiA9IDA7YCxcbiAgICAgIGBpZiAoJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX0gJHthdHRyaWJ1dGVzLnNlbGVjdExhc3RJbmRleCA+IDAgPyAnPD0nIDogJzwnfSB2YWx1ZSkge1xuICAgICAgICAgdmFsdWUgPSAke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfTtcbiAgICAgICAgIGJlc3RfaW5kZXggPSBpMzIobGFzdF9pbmRleCk7XG4gICAgICAgfWAsXG4gICAgICAnJyxcbiAgICAgIG91dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICdiZXN0X2luZGV4JyksXG4gICAgXTtcbiAgfTtcblxuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlUmVkdWNlUHJvZ3JhbUluZm8oXG4gICAgICAnQXJnTWluJyxcbiAgICAgIHsgaGludDogYXR0cmlidXRlcy5jYWNoZUtleSwgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuayddIH0sXG4gICAgICBbY29udGV4dC5pbnB1dHNbMF1dLFxuICAgICAgYXJnTWluTWF4T3AsXG4gICAgICBbYXR0cmlidXRlcy5heGlzXSxcbiAgICAgIERhdGFUeXBlLmludDY0LFxuICAgICAgYXR0cmlidXRlcy5rZWVwRGltcyxcbiAgICApLFxuICAgIHsgaW5wdXRzOiBbMF0gfSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBhcmdNYXggPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEFyZ01pbk1heEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCBhcmdNaW5NYXhPcDogUmVkdWNlT3AgPSAoaW5wdXQsIG91dHB1dCwgYXhlcykgPT4ge1xuICAgIGNvbnN0IGlkeFplcm8gPSBbXTtcbiAgICBmb3IgKGxldCBrID0gMDsgayA8IGlucHV0LnJhbms7IGsrKykge1xuICAgICAgaWYgKGF4ZXMuaW5kZXhPZihrKSA+PSAwIHx8IGF4ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGlkeFplcm8ucHVzaChgaW5wdXRfaW5kaWNlc1ske2t9XSA9IDA7YCk7IC8vIGZpcnN0IGVsZW1lbnRcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFtcbiAgICAgIGAke2lkeFplcm8uam9pbignXFxuJyl9YCxcbiAgICAgIGB2YXIgdmFsdWUgPSAke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfTtcXG52YXIgYmVzdF9pbmRleCA6IGkzMiA9IDA7YCxcbiAgICAgIGBpZiAoJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX0gJHthdHRyaWJ1dGVzLnNlbGVjdExhc3RJbmRleCA+IDAgPyAnPj0nIDogJz4nfSB2YWx1ZSkge1xuICAgICAgICAgdmFsdWUgPSAke2lucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlcycpfTtcbiAgICAgICAgIGJlc3RfaW5kZXggPSBpMzIobGFzdF9pbmRleCk7XG4gICAgICAgfWAsXG4gICAgICAnJyxcbiAgICAgIG91dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICdiZXN0X2luZGV4JyksXG4gICAgXTtcbiAgfTtcblxuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlUmVkdWNlUHJvZ3JhbUluZm8oXG4gICAgICAnYXJnTWF4JyxcbiAgICAgIHsgaGludDogYXR0cmlidXRlcy5jYWNoZUtleSwgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuayddIH0sXG4gICAgICBbY29udGV4dC5pbnB1dHNbMF1dLFxuICAgICAgYXJnTWluTWF4T3AsXG4gICAgICBbYXR0cmlidXRlcy5heGlzXSxcbiAgICAgIERhdGFUeXBlLmludDY0LFxuICAgICAgYXR0cmlidXRlcy5rZWVwRGltcyxcbiAgICApLFxuICAgIHsgaW5wdXRzOiBbMF0gfSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUFyZ01pbk1heEF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBBcmdNaW5NYXhBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleShhdHRyaWJ1dGVzIGFzIE9taXQ8QXJnTWluTWF4QXR0cmlidXRlcywga2V5b2YgQXR0cmlidXRlV2l0aENhY2hlS2V5Pik7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIEdwdURhdGFUeXBlLCBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeSwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGdldE1heENvbXBvbmVudHMsXG4gIEluZGljZXNIZWxwZXIsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSxcbiAgdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZSxcbiAgVW5pZm9ybURhdGFFbGVtZW50VHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGNvbnN0IGVudW0gQXR0ZW50aW9uUWt2Rm9ybWF0IHtcbiAgdW5rbm93biwgLy8gZW51bSB2YWx1ZSBub3Qgc2V0LCBvciBkZXBlbmRzIG9uIHFrdiBwcm9qZWN0aW9uIGltcGxlbWVudGF0aW9uIGRldGFpbHNcbiAgcWt2Qk5TSCwgLy8gZm9yIG5vbi1wYWNrZWQgcWt2LCBwZXJtdXRlZFxuICBxa3ZCU05ILCAvLyBmb3Igbm9uLXBhY2tlZCBxa3YsIG5vdCBwZXJtdXRlZCwgdXNlZCBieSBtZW1vcnkgZWZmaWNpZW50IGF0dGVudGlvbiBvciBNdWx0aUhlYWRBdHRlbnRpb25cbiAgcWt2QlNOM0gsIC8vIGZvciBUUlQgZnVzZWQgYXR0ZW50aW9uLCBxa3YgYXJlIHBhY2tlZFxuICBxa3ZCTlNIcWt2QlMzTkgsIC8vIGZvciBUUlQgZnVzZWQgY2F1c2FsIGF0dGVudGlvbiwgZGF0YSBoYXMgdHdvIGZvcm1hdHMgKHFrdiBpcyAzQk5TSCwgZ2VtbV9idWZmZXIgaXMgQlMzTkgpXG4gIHFLdkJTTkh4QlNOMkgsIC8vIGZvciBUUlQgZnVzZWQgY3Jvc3MgYXR0ZW50aW9uLCBrdiBhcmUgcGFja2VkXG4gIHFrdlROSCwgLy8gZm9yIG1lbW9yeSBlZmZpY2llbnQgYXR0ZW50aW9uLCBxa3YgYXJlIG5vdCBwYWNrZWQsIGFuZCBwYWRkaW5ncyBhcmUgcmVtb3ZlZC5cbiAgcWt2VE4zSCwgLy8gZm9yIFRSVCBmdXNlZCBhdHRlbnRpb24sIHFrdiBhcmUgcGFja2VkIGFuZCBwYWRkaW5ncyBhcmUgcmVtb3ZlZFxufVxuXG5leHBvcnQgY29uc3QgZW51bSBBdHRlbnRpb25NYXNrVHlwZSB7XG4gIG5vbmUsIC8vIE5vIG1hc2tcbiAgbWFzazFkS2V5U2VxTGVuLCAvLyBbYmF0Y2hfc2l6ZV0sIGtleSBzZXF1ZW5jZSBsZW5ndGhcbiAgbWFzazFkRW5kU3RhcnQsIC8vIFsyICogYmF0Y2hfc2l6ZV0gd2l0aCBlbmQgcG9zaXRpb25zIGFuZCBzdGFydCBwb3NpdGlvbnNcbiAgbWFzazFES2V5U2VxTGVuU3RhcnQsIC8vIFszICogYmF0Y2hfc2l6ZSArIDJdIHdpdGggW2tleV9sZW5bMF0sIC4uLiwga2V5X2xlbltiYXRjaF9zaXplIC0gMV0sIHF1ZXJ5X3N0YXJ0WzBdLFxuICAvLyAuLi4sIHF1ZXJ5X3N0YXJ0W2JhdGNoX3NpemUgLSAxXSwgcXVlcnlfZW5kW2JhdGNoX3NpemUgLSAxXSwga2V5X3N0YXJ0WzBdLCAuLi4sXG4gIC8vIGtleV9zdGFydFtiYXRjaF9zaXplIC0gMV0sIGtleV9lbmRbYmF0Y2hfc2l6ZSAtIDFdXVxuICBtYXNrMmREdW1teSwgLy8gZHVtbXkgbWFzayB3aXRoIHNoYXBlIFsxLCAxXSBvciBbYmF0Y2hfc2l6ZSwgMV0uIEl0IGhhcyBzYW1lIGVmZmVjdCBhcyBubyBtYXNrLlxuICBtYXNrMmRLZXlQYWRkaW5nLCAvLyBbYmF0Y2hfc2l6ZSwgdG90YWxfc2VxdWVuY2VfbGVuZ3RoXVxuICBtYXNrM2RBdHRlbnRpb24sIC8vIFtiYXRjaF9zaXplLCBzZXF1ZW5jZV9sZW5ndGgsIHRvdGFsX3NlcXVlbmNlX2xlbmd0aF1cbiAgbWFzazRkTWVnYXRyb24sIC8vIE1lZ2F0cm9uIGNhdXNhbCBtYXNrIHdpdGggc2hhcGUgW2JhdGNoX3NpemUsIDEsIG1heF9zZXF1ZW5jZV9sZW5ndGgsIG1heF9zZXF1ZW5jZV9sZW5ndGhdXG4gIG1hc2tVbmtub3duLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEF0dGVudGlvblBhcmFtZXRlcnMge1xuICBiYXRjaFNpemU6IG51bWJlcjtcbiAgc2VxdWVuY2VMZW5ndGg6IG51bWJlcjtcbiAgcGFzdFNlcXVlbmNlTGVuZ3RoOiBudW1iZXI7XG4gIGt2U2VxdWVuY2VMZW5ndGg6IG51bWJlcjtcbiAgdG90YWxTZXF1ZW5jZUxlbmd0aDogbnVtYmVyO1xuICBtYXhTZXF1ZW5jZUxlbmd0aDogbnVtYmVyO1xuICBpbnB1dEhpZGRlblNpemU6IG51bWJlcjtcbiAgaGlkZGVuU2l6ZTogbnVtYmVyO1xuICB2SGlkZGVuU2l6ZTogbnVtYmVyO1xuICBoZWFkU2l6ZTogbnVtYmVyO1xuICB2SGVhZFNpemU6IG51bWJlcjtcbiAgbnVtSGVhZHM6IG51bWJlcjtcbiAga3ZOdW1IZWFkcz86IG51bWJlcjtcbiAgblJlcHM/OiBudW1iZXI7XG4gIGlzVW5pZGlyZWN0aW9uYWw/OiBib29sZWFuO1xuICBwYXN0UHJlc2VudFNoYXJlQnVmZmVyOiBib29sZWFuO1xuICBtYXNrRmlsdGVyVmFsdWU/OiBudW1iZXI7XG4gIG1hc2tUeXBlOiBBdHRlbnRpb25NYXNrVHlwZTtcbiAgc2NhbGU6IG51bWJlcjtcbiAgYnJvYWRjYXN0UmVzUG9zQmlhczogYm9vbGVhbjtcbiAgcGFzc1Bhc3RJbkt2OiBib29sZWFuO1xuICBxa3ZGb3JtYXQ6IEF0dGVudGlvblFrdkZvcm1hdDtcbiAgc29mdGNhcD86IG51bWJlcjtcbiAgZG9Sb3Rhcnk/OiBudW1iZXI7XG4gIHJvdGFyeUludGVyTGVhdmVkPzogbnVtYmVyO1xuICBzb21tb290aFNvZnRtYXg/OiBudW1iZXI7XG4gIGxvY2FsV2luZG93c1NpemU/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXR0ZW50aW9uQXR0cnMge1xuICBudW1IZWFkczogbnVtYmVyO1xuICBpc1VuaWRpcmVjdGlvbmFsOiBudW1iZXI7XG4gIG1hc2tGaWx0ZXJWYWx1ZTogbnVtYmVyO1xuICBzY2FsZTogbnVtYmVyO1xuICBkb1JvdGFyeTogbnVtYmVyO1xuICBxa3ZIaWRkZW5TaXplczogbnVtYmVyW107XG4gIHBhc3RQcmVzZW50U2hhcmVCdWZmZXI6IGJvb2xlYW47XG59XG5cbmNvbnN0IHZhbGlkYXRlQXR0ZW50aW9uSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBBdHRlbnRpb25BdHRycyk6IEF0dGVudGlvblBhcmFtZXRlcnMgPT4ge1xuICAvLyBBYmJyZXZpYXRpb24gYW5kIE1lYW5pbmdzOlxuICAvLyAgIEI6ICAgIGJhdGNoX3NpemVcbiAgLy8gICBTOiAgICBzZXF1ZW5jZV9sZW5ndGggKGlucHV0IHNlcXVlbmNlIGxlbmd0aCBvZiBxdWVyeSlcbiAgLy8gICBQOiAgICBwYXN0X3NlcXVlbmNlX2xlbmd0aCAocGFzdCBzZXF1ZW5jZSBsZW5ndGggb2Yga2V5IG9yIHZhbHVlKVxuICAvLyAgIEw6ICAgIGt2X3NlcXVlbmNlX2xlbmd0aCAoaW5wdXQgc2VxdWVuY2UgbGVuZ3RoIG9mIGtleSBvciB2YWx1ZSlcbiAgLy8gICBNOiAgICBtYXhfc2VxdWVuY2VfbGVuZ3RoXG4gIC8vICAgVDogICAgdG90YWxfc2VxdWVuY2VfbGVuZ3RoID0gcGFzdF9zZXF1ZW5jZV9sZW5ndGggKyBrdl9zZXF1ZW5jZV9sZW5ndGhcbiAgLy8gICBOOiAgICBudW1faGVhZHNcbiAgLy8gICBIOiAgICBoZWFkIHNpemUgZm9yIFEgYW5kIEssIGFrYSBxX2hlYWRfc2l6ZSBvciBrX2hlYWRfc2l6ZSBvciBxa19oZWFkX3NpemVcbiAgLy8gICBIX3Y6ICB2X2hlYWRfc2l6ZVxuICAvLyAgIERfaTogIGlucHV0IGhpZGRlbiBzaXplXG4gIC8vICAgRDogICAgaGlkZGVuIHNpemUgZm9yIFEgYW5kIEsgKEQgPSBOICogSCksIGFrYSBxX2hpZGRlbl9zaXplIG9yIGtfaGlkZGVuX3NpemUgb3IgcWtfaGlkZGVuX3NpemVcbiAgLy8gICBEX3Y6ICB2X2hpZGRlbl9zaXplID0gbnVtX2hlYWRzICogdl9oZWFkX3NpemVcblxuICAvLyBXaGVuIHBhc3Qgc3RhdGUgaXMgdXNlZCwgUSwgSyBhbmQgViBzaG91bGQgaGF2ZSBzYW1lIGhpZGRlbiBzaXplICh1bmxlc3Mgd2Ugc3BsaXQgaXQgaW50byBwYXN0X2tleSBhbmQgcGFzdF92YWx1ZSkuXG5cbiAgLy8gSW5wdXQgc2hhcGVzOlxuICAvLyAgIGlucHV0ICAgICAgICAoUS9LL1YpICAgIDogKEIsIFMsIERfaSlcbiAgLy8gICB3ZWlnaHRzICAgICAgKFEvSy9WKSAgICA6IChEX2ksIEQgKyBEICsgRF92KVxuICAvLyAgIGJpYXMgICAgICAgICAoUS9LL1YpICAgIDogKEQgKyBEICsgRF92KVxuICAvLyAgIG1hc2tfaW5kZXggICAgICAgICAgICAgIDogc2VlIGJlbG93XG4gIC8vICAgcGFzdCAgICAgICAgIChLL1YpICAgICAgOiAoMiwgQiwgTiwgUCwgSCkgb3IgTlVMTFxuICAvLyAgIGF0dGVudGlvbl9iaWFzICAgICAgICAgIDogKEIsIE4sIFMsIFQpIG9yIE5VTExcblxuICAvLyBGb3IgbWFza19pbmRleCwgdGhlIGZvbGxvd2luZyBzaGFwZXMgYXJlIHN1cHBvcnRlZDpcbiAgLy8gICAgIE5VTEwsIChCLCAxKSwgKDEsIDEpXG4gIC8vICAgICAoQiksICgyICogQiksICgzICogQiArIDIpXG4gIC8vICAgICAoQiwgVClcbiAgLy8gICAgIChCLCBTLCBUKVxuICAvLyAgICAgKEIsIDEsIE0sIE0pXG4gIC8vXG4gIC8vIFdoZW4gYSBtb2RlbCBpcyBwcnVuZWQgKGxpa2Ugc29tZSBhdHRlbnRpb24gaGVhZHMgYXJlIHJlbW92ZWQgaW4gUS9LL1YpLCBpbnB1dF9oaWRkZW5fc2l6ZSBjb3VsZCBiZSBsYXJnZXJcbiAgLy8gdGhhbiBoaWRkZW4gZGltZW5zaW9uIG9mIFEsIEsgYW5kIFYuXG5cbiAgY29uc3QgaW5wdXQgPSBpbnB1dHNbMF07XG4gIGNvbnN0IHdlaWdodHMgPSBpbnB1dHNbMV07XG4gIGNvbnN0IGJpYXMgPSBpbnB1dHNbMl07XG4gIGNvbnN0IG1hc2tJbmRleCA9IGlucHV0c1szXTtcbiAgY29uc3QgcGFzdCA9IGlucHV0c1s0XTtcbiAgY29uc3QgYXR0ZW50aW9uQmlhcyA9IGlucHV0c1s1XTtcblxuICBpZiAocGFzdCAmJiBhdHRlbnRpb25CaWFzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdBdHRlbnRpb24gY2Fubm90IGhhdmUgYm90aCBwYXN0IGFuZCBhdHRlbnRpb25fYmlhcycpO1xuICB9XG5cbiAgaWYgKGlucHV0LmRpbXMubGVuZ3RoICE9PSAzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcImlucHV0XCIgbXVzdCBoYXZlIDMgZGltZW5zaW9ucycpO1xuICB9XG5cbiAgY29uc3QgYmF0Y2hTaXplID0gaW5wdXQuZGltc1swXTtcbiAgY29uc3Qgc2VxdWVuY2VMZW5ndGggPSBpbnB1dC5kaW1zWzFdO1xuICBjb25zdCBpbnB1dEhpZGRlblNpemUgPSBpbnB1dC5kaW1zWzJdO1xuXG4gIGlmIChiaWFzLmRpbXMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcImJpYXNcIiBpcyBleHBlY3RlZCB0byBoYXZlIDEgZGltZW5zaW9ucycpO1xuICB9XG5cbiAgaWYgKHdlaWdodHMuZGltcy5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwid2VpZ2h0c1wiIGlzIGV4cGVjdGVkIHRvIGhhdmUgMiBkaW1lbnNpb25zJyk7XG4gIH1cblxuICBpZiAod2VpZ2h0cy5kaW1zWzBdICE9PSBpbnB1dEhpZGRlblNpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IDEgZGltZW5zaW9uIDAgc2hvdWxkIGhhdmUgc2FtZSBsZW5ndGggYXMgZGltZW5zaW9uIDIgb2YgaW5wdXQgMCcpO1xuICB9XG5cbiAgaWYgKGJpYXMuZGltc1swXSAhPT0gd2VpZ2h0cy5kaW1zWzFdKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcImJpYXNcIiBkaW1lbnNpb24gMCBzaG91bGQgaGF2ZSBzYW1lIGxlbmd0aCBhcyBkaW1lbnNpb24gMSBvZiBpbnB1dCBcIndlaWdodHNcIicpO1xuICB9XG5cbiAgbGV0IHFIaWRkZW5TaXplID0gYmlhcy5kaW1zWzBdIC8gMztcbiAgbGV0IGtIaWRkZW5TaXplID0gcUhpZGRlblNpemU7XG4gIGxldCB2SGlkZGVuU2l6ZSA9IGtIaWRkZW5TaXplO1xuICBpZiAoYXR0cmlidXRlcy5xa3ZIaWRkZW5TaXplcy5sZW5ndGggPiAwKSB7XG4gICAgaWYgKGF0dHJpYnV0ZXMucWt2SGlkZGVuU2l6ZXMubGVuZ3RoICE9PSAzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Frdl9oaWRkZW5fc2l6ZXMgYXR0cmlidXRlIHNob3VsZCBoYXZlIDMgZWxlbWVudHMnKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBzeiBvZiBhdHRyaWJ1dGVzLnFrdkhpZGRlblNpemVzKSB7XG4gICAgICBpZiAoc3ogJSBhdHRyaWJ1dGVzLm51bUhlYWRzICE9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigncWt2X2hpZGRlbl9zaXplcyBzaG91bGQgYmUgZGl2aXNpYmxlIGJ5IG51bV9oZWFkcycpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHFIaWRkZW5TaXplID0gYXR0cmlidXRlcy5xa3ZIaWRkZW5TaXplc1swXTtcbiAgICBrSGlkZGVuU2l6ZSA9IGF0dHJpYnV0ZXMucWt2SGlkZGVuU2l6ZXNbMV07XG4gICAgdkhpZGRlblNpemUgPSBhdHRyaWJ1dGVzLnFrdkhpZGRlblNpemVzWzJdO1xuICB9XG5cbiAgY29uc3Qga3ZTZXF1ZW5jZUxlbmd0aCA9IHNlcXVlbmNlTGVuZ3RoO1xuXG4gIGlmIChxSGlkZGVuU2l6ZSAhPT0ga0hpZGRlblNpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Frdl9oaWRkZW5fc2l6ZXMgZmlyc3QgZWxlbWVudCBzaG91bGQgYmUgc2FtZSBhcyB0aGUgc2Vjb25kJyk7XG4gIH1cblxuICBpZiAoYmlhcy5kaW1zWzBdICE9PSBxSGlkZGVuU2l6ZSArIGtIaWRkZW5TaXplICsgdkhpZGRlblNpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwiYmlhc1wiIGRpbWVuc2lvbiAwIHNob3VsZCBoYXZlIHNhbWUgbGVuZ3RoIGFzIHN1bSBvZiBRL0svViBoaWRkZW4gc2l6ZXMnKTtcbiAgfVxuXG4gIGxldCBwYXN0U2VxdWVuY2VMZW5ndGggPSAwO1xuICBpZiAocGFzdCkge1xuICAgIGlmIChrSGlkZGVuU2l6ZSAhPT0gdkhpZGRlblNpemUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0XCIgZXhwZWN0IGtfaGlkZGVuX3NpemUgPT0gdl9oaWRkZW5fc2l6ZScpO1xuICAgIH1cbiAgICBpZiAocGFzdC5kaW1zLmxlbmd0aCAhPT0gNSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInBhc3RcIiBtdXN0IGhhdmUgNSBkaW1lbnNpb25zJyk7XG4gICAgfVxuICAgIGlmIChwYXN0LmRpbXNbMF0gIT09IDIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0XCIgZmlyc3QgZGltZW5zaW9uIG11c3QgYmUgMicpO1xuICAgIH1cbiAgICBpZiAocGFzdC5kaW1zWzFdICE9PSBiYXRjaFNpemUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0XCIgc2Vjb25kIGRpbWVuc2lvbiBtdXN0IGJlIGJhdGNoX3NpemUnKTtcbiAgICB9XG4gICAgaWYgKHBhc3QuZGltc1syXSAhPT0gYXR0cmlidXRlcy5udW1IZWFkcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInBhc3RcIiB0aGlyZCBkaW1lbnNpb24gbXVzdCBiZSBudW1faGVhZHMnKTtcbiAgICB9XG4gICAgaWYgKHBhc3QuZGltc1s0XSAhPT0ga0hpZGRlblNpemUgLyBhdHRyaWJ1dGVzLm51bUhlYWRzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicGFzdFwiIGZpZnRoIGRpbWVuc2lvbiBtdXN0IGJlIGtfaGlkZGVuX3NpemUgLyBudW1faGVhZHMnKTtcbiAgICB9XG5cbiAgICBpZiAoIWF0dHJpYnV0ZXMucGFzdFByZXNlbnRTaGFyZUJ1ZmZlcikge1xuICAgICAgcGFzdFNlcXVlbmNlTGVuZ3RoID0gcGFzdC5kaW1zWzNdO1xuICAgIH1cbiAgICAvLyBUT0RPOiBoYW5kbGUgcGFzdF9zZXFfbGVuXG4gIH1cblxuICBjb25zdCB0b3RhbFNlcXVlbmNlTGVuZ3RoID0ga3ZTZXF1ZW5jZUxlbmd0aCArIHBhc3RTZXF1ZW5jZUxlbmd0aDtcbiAgY29uc3QgbWF4U2VxdWVuY2VMZW5ndGggPSAtMTtcblxuICBjb25zdCBtYXNrVHlwZSA9IEF0dGVudGlvbk1hc2tUeXBlLm5vbmU7XG4gIGlmIChtYXNrSW5kZXgpIHtcbiAgICAvLyBtYXNrVHlwZSA9IEF0dGVudGlvbk1hc2tUeXBlLk1BU0tfVU5LTk9XTjtcbiAgICAvLyBUT0RPOiBoYW5kbGUgbWFza1xuICAgIHRocm93IG5ldyBFcnJvcignTWFzayBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cblxuICBpZiAocGFzdCkge1xuICAgIHRocm93IG5ldyBFcnJvcigncGFzdCBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cblxuICBpZiAoYXR0ZW50aW9uQmlhcykge1xuICAgIGlmIChhdHRlbnRpb25CaWFzLmRpbXMubGVuZ3RoICE9PSA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwiYXR0ZW50aW9uX2JpYXNcIiBtdXN0IGhhdmUgNCBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBicm9hZGNhc3RpbmcgdGhlIGZpcnN0IGFuZCBzZWNvbmQgZGltZW5zaW9ucyBvZiBhdHRlbnRpb25fYmlhc1xuICAgIGlmIChcbiAgICAgIGF0dGVudGlvbkJpYXMuZGltc1swXSAhPT0gYmF0Y2hTaXplIHx8XG4gICAgICBhdHRlbnRpb25CaWFzLmRpbXNbMV0gIT09IGF0dHJpYnV0ZXMubnVtSGVhZHMgfHxcbiAgICAgIGF0dGVudGlvbkJpYXMuZGltc1syXSAhPT0gc2VxdWVuY2VMZW5ndGggfHxcbiAgICAgIGF0dGVudGlvbkJpYXMuZGltc1szXSAhPT0gdG90YWxTZXF1ZW5jZUxlbmd0aFxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3QgXCJhdHRlbnRpb25fYmlhc1wiIHNoYXBlIChiYXRjaF9zaXplLCBudW1faGVhZHMsIHNlcXVlbmNlX2xlbmd0aCwgdG90YWxfc2VxdWVuY2VfbGVuZ3RoKScpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgYmF0Y2hTaXplLFxuICAgIHNlcXVlbmNlTGVuZ3RoLFxuICAgIHBhc3RTZXF1ZW5jZUxlbmd0aCxcbiAgICBrdlNlcXVlbmNlTGVuZ3RoLFxuICAgIHRvdGFsU2VxdWVuY2VMZW5ndGgsXG4gICAgbWF4U2VxdWVuY2VMZW5ndGgsXG4gICAgaW5wdXRIaWRkZW5TaXplLFxuICAgIGhpZGRlblNpemU6IHFIaWRkZW5TaXplLFxuICAgIHZIaWRkZW5TaXplLFxuICAgIGhlYWRTaXplOiBNYXRoLmZsb29yKHFIaWRkZW5TaXplIC8gYXR0cmlidXRlcy5udW1IZWFkcyksXG4gICAgdkhlYWRTaXplOiBNYXRoLmZsb29yKHZIaWRkZW5TaXplIC8gYXR0cmlidXRlcy5udW1IZWFkcyksXG4gICAgbnVtSGVhZHM6IGF0dHJpYnV0ZXMubnVtSGVhZHMsXG4gICAgaXNVbmlkaXJlY3Rpb25hbDogZmFsc2UsXG4gICAgcGFzdFByZXNlbnRTaGFyZUJ1ZmZlcjogZmFsc2UsXG4gICAgbWFza0ZpbHRlclZhbHVlOiBhdHRyaWJ1dGVzLm1hc2tGaWx0ZXJWYWx1ZSxcbiAgICBtYXNrVHlwZSxcbiAgICBzY2FsZTogYXR0cmlidXRlcy5zY2FsZSxcbiAgICBicm9hZGNhc3RSZXNQb3NCaWFzOiBmYWxzZSxcbiAgICBwYXNzUGFzdEluS3Y6IGZhbHNlLFxuICAgIHFrdkZvcm1hdDogQXR0ZW50aW9uUWt2Rm9ybWF0LnFrdkJOU0gsXG4gIH07XG59O1xuXG5jb25zdCBpbml0VmFyU3R1YiA9IChcbiAgc2VxTGVuc0lucHV0OiBJbmRpY2VzSGVscGVyIHwgdW5kZWZpbmVkLFxuICB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQ6IEluZGljZXNIZWxwZXIgfCB1bmRlZmluZWQsXG4gIGluaXRQYXN0U2VxdWVuY2VMZW5ndGg6IGJvb2xlYW4sXG4pID0+IHtcbiAgLy8gSW4gdGhlIGNhc2Ugb2YgR1FBLCByZWRlZmluZSB0b3RhbF9zZXF1ZW5jZV9sZW5ndGgsIHByZXNlbnRfc2VxdWVuY2VfbGVuZ3RoIGFuZCBwYXN0X3NlcXVlbmNlX2xlbmd0aCBiYXNlZCBvbiBzZXFsZW5fayBpbnB1dFxuICBpZiAodG90YWxTZXF1ZW5jZUxlbmd0aElucHV0ICYmIHNlcUxlbnNJbnB1dCkge1xuICAgIHJldHVybiBgXG4gICAgICBsZXQgdG90YWxfc2VxdWVuY2VfbGVuZ3RoX2lucHV0ID0gdTMyKCR7dG90YWxTZXF1ZW5jZUxlbmd0aElucHV0LmdldEJ5T2Zmc2V0KCcwJyl9KTtcbiAgICAgIGxldCBwcmVzZW50X3NlcXVlbmNlX2xlbmd0aCA9IG1heCh0b3RhbF9zZXF1ZW5jZV9sZW5ndGhfaW5wdXQsIHVuaWZvcm1zLnBhc3Rfc2VxdWVuY2VfbGVuZ3RoKTtcbiAgICAgIGxldCBpc19zdWJzZXF1ZW50X3Byb21wdDogYm9vbCA9IHNlcXVlbmNlX2xlbmd0aCA+IDEgJiYgc2VxdWVuY2VfbGVuZ3RoICE9IHRvdGFsX3NlcXVlbmNlX2xlbmd0aF9pbnB1dDtcbiAgICAgIGxldCBpc19maXJzdF9wcm9tcHQ6IGJvb2wgPSBpc19zdWJzZXF1ZW50X3Byb21wdCA9PSBmYWxzZSAmJiBzZXF1ZW5jZV9sZW5ndGggPT0gdG90YWxfc2VxdWVuY2VfbGVuZ3RoX2lucHV0O1xuICAgICAgdG90YWxfc2VxdWVuY2VfbGVuZ3RoID0gdTMyKCR7c2VxTGVuc0lucHV0Py5nZXRCeU9mZnNldCgnYmF0Y2hJZHgnKX0pICsgMTtcbiAgICAgIHZhciBwYXN0X3NlcXVlbmNlX2xlbmd0aDogdTMyID0gMDtcbiAgICAgIGlmIChpc19maXJzdF9wcm9tcHQgPT0gZmFsc2UpIHtcbiAgICAgICAgcGFzdF9zZXF1ZW5jZV9sZW5ndGggPSB0b3RhbF9zZXF1ZW5jZV9sZW5ndGggLSBzZXF1ZW5jZV9sZW5ndGg7XG4gICAgICB9XG4gICAgICAgYDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYFxuICAgICR7aW5pdFBhc3RTZXF1ZW5jZUxlbmd0aCA/ICdsZXQgcGFzdF9zZXF1ZW5jZV9sZW5ndGggPSB1bmlmb3Jtcy5wYXN0X3NlcXVlbmNlX2xlbmd0aCcgOiAnJ307XG4gICAgbGV0IHByZXNlbnRfc2VxdWVuY2VfbGVuZ3RoID0gdG90YWxfc2VxdWVuY2VfbGVuZ3RoO1xuICAgIGA7XG4gIH1cbn07XG5cbmNvbnN0IGNyZWF0ZUluUGxhY2VTb2Z0bWF4UHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0OiBUZW5zb3JWaWV3LFxuICBiYXRjaFNpemU6IG51bWJlcixcbiAgbnVtSGVhZHM6IG51bWJlcixcbiAgcGFzdFNlcXVlbmNlTGVuZ3RoOiBudW1iZXIsXG4gIHNlcXVlbmNlTGVuZ3RoOiBudW1iZXIsXG4gIHRvdGFsU2VxdWVuY2VMZW5ndGg6IG51bWJlcixcbiAgc2VxTGVuczogVGVuc29yVmlldyB8IHVuZGVmaW5lZCxcbiAgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0OiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuKSA9PiB7XG4gIC8vIFNldCBjb21wb25lbnRzIHRvIDEgaWYgc2VxTGVucyBpcyBzcGVjaWZpZWQsIGkuZS4gR3JvdXBRdWVyeUF0dGVudGlvbi5cbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoc2VxTGVucyA/IDEgOiB0b3RhbFNlcXVlbmNlTGVuZ3RoKTtcbiAgbGV0IFdHID0gNjQ7XG4gIGNvbnN0IHRvdGFsU2VxdWVuY2VMZW5ndGhDb21wID0gdG90YWxTZXF1ZW5jZUxlbmd0aCAvIGNvbXBvbmVudHM7XG4gIGlmICh0b3RhbFNlcXVlbmNlTGVuZ3RoQ29tcCA8IFdHKSB7XG4gICAgV0cgPSAzMjtcbiAgfVxuICBjb25zdCBlbGVtZW50c1BlclRocmVhZCA9IE1hdGguY2VpbCh0b3RhbFNlcXVlbmNlTGVuZ3RoIC8gY29tcG9uZW50cyAvIFdHKTtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBiYXRjaFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogbnVtSGVhZHMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFzdFNlcXVlbmNlTGVuZ3RoIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHNlcXVlbmNlTGVuZ3RoIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHRvdGFsU2VxdWVuY2VMZW5ndGhDb21wIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGVsZW1lbnRzUGVyVGhyZWFkIH0sXG4gIF07XG4gIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKGlucHV0LmRhdGFUeXBlLCBjb21wb25lbnRzKTtcbiAgY29uc3QgZjMyVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoRGF0YVR5cGUuZmxvYXQsIGNvbXBvbmVudHMpO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsndHlwZSddO1xuICBpZiAoc2VxTGVucykge1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3R5cGUnKTtcbiAgfVxuICBpZiAodG90YWxTZXF1ZW5jZUxlbmd0aElucHV0KSB7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgndHlwZScpO1xuICB9XG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGlucHV0SGVscGVyID0gb3V0cHV0VmFyaWFibGUoJ3gnLCBpbnB1dC5kYXRhVHlwZSwgaW5wdXQuZGltcywgY29tcG9uZW50cyk7XG4gICAgY29uc3QgaW5wdXRIZWxwZXJzID0gW2lucHV0SGVscGVyXTtcbiAgICBjb25zdCBzZXFMZW5zSW5wdXRIZWxwZXIgPSBzZXFMZW5zID8gaW5wdXRWYXJpYWJsZSgnc2VxX2xlbnMnLCBzZXFMZW5zLmRhdGFUeXBlLCBzZXFMZW5zLmRpbXMpIDogdW5kZWZpbmVkO1xuICAgIGlmIChzZXFMZW5zSW5wdXRIZWxwZXIpIHtcbiAgICAgIGlucHV0SGVscGVycy5wdXNoKHNlcUxlbnNJbnB1dEhlbHBlcik7XG4gICAgfVxuXG4gICAgY29uc3QgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0SGVscGVyID0gdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0XG4gICAgICA/IGlucHV0VmFyaWFibGUoJ3RvdGFsX3NlcXVlbmNlX2xlbmd0aF9pbnB1dCcsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dC5kYXRhVHlwZSwgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0LmRpbXMpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgICBpZiAodG90YWxTZXF1ZW5jZUxlbmd0aElucHV0SGVscGVyKSB7XG4gICAgICBpbnB1dEhlbHBlcnMucHVzaCh0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXRIZWxwZXIpO1xuICAgIH1cbiAgICBjb25zdCBlbGVtVmFsdWVUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShpbnB1dC5kYXRhVHlwZSk7XG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnYmF0Y2hfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdudW1faGVhZHMnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAncGFzdF9zZXF1ZW5jZV9sZW5ndGgnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnc2VxdWVuY2VfbGVuZ3RoJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3RvdGFsX3NlcXVlbmNlX2xlbmd0aCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdlbGVtZW50c19wZXJfdGhyZWFkJywgdHlwZTogJ3UzMicgfSxcbiAgICBdO1xuXG4gICAgcmV0dXJuIGBcbiAgdmFyPHdvcmtncm91cD4gdGhyZWFkX21heDogYXJyYXk8ZjMyLCAke1dHfT47XG4gIHZhcjx3b3JrZ3JvdXA+IHRocmVhZF9zdW06IGFycmF5PGYzMiwgJHtXR30+O1xuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKC4uLmlucHV0SGVscGVycyl9XG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydChbV0csIDEsIDFdKX1cbiAgICBsZXQgYmF0Y2hJZHggPSB3b3JrZ3JvdXBfaWQueiAvIHVuaWZvcm1zLm51bV9oZWFkcztcbiAgICBsZXQgaGVhZElkeCA9IHdvcmtncm91cF9pZC56ICUgdW5pZm9ybXMubnVtX2hlYWRzO1xuICAgIGxldCBzZXF1ZW5jZV9sZW5ndGggPSB1bmlmb3Jtcy5zZXF1ZW5jZV9sZW5ndGg7XG4gICAgdmFyIHRvdGFsX3NlcXVlbmNlX2xlbmd0aCA9IHVuaWZvcm1zLnRvdGFsX3NlcXVlbmNlX2xlbmd0aDtcbiAgICAke2luaXRWYXJTdHViKHNlcUxlbnNJbnB1dEhlbHBlciwgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0SGVscGVyLCBmYWxzZSl9XG4gICAgbGV0IGxvY2FsX29mZnNldCA9IGxvY2FsX2lkeCAqIHVuaWZvcm1zLmVsZW1lbnRzX3Blcl90aHJlYWQ7XG4gICAgbGV0IG9mZnNldCA9IChnbG9iYWxfaWR4IC8gJHtXR30pICogdW5pZm9ybXMudG90YWxfc2VxdWVuY2VfbGVuZ3RoICsgbG9jYWxfb2Zmc2V0O1xuICAgIGxldCBzZXFfY2F1c2FsX2xlbmd0aCA9ICR7c2VxTGVucyA/ICd1MzIocGFzdF9zZXF1ZW5jZV9sZW5ndGggKyB3b3JrZ3JvdXBfaWQueSArIDEpJyA6ICd0b3RhbF9zZXF1ZW5jZV9sZW5ndGgnfTtcbiAgICB2YXIgdGhyZWFkX21heF92ZWN0b3IgPSAke2YzMlR5cGV9KC0zLjQwMjgyM2UrMzhmKTtcbiAgICBmb3IgKHZhciBpOiB1MzIgPSAwOyBpIDwgdW5pZm9ybXMuZWxlbWVudHNfcGVyX3RocmVhZCAmJiBpICsgbG9jYWxfb2Zmc2V0IDwgc2VxX2NhdXNhbF9sZW5ndGg7IGkrKykge1xuICAgICAgdGhyZWFkX21heF92ZWN0b3IgPSBtYXgoJHtmMzJUeXBlfSh4W29mZnNldCArIGldKSwgdGhyZWFkX21heF92ZWN0b3IpO1xuICAgIH1cbiAgICB0aHJlYWRfbWF4W2xvY2FsX2lkeF0gPSAkeygoKSA9PiB7XG4gICAgICBzd2l0Y2ggKGNvbXBvbmVudHMpIHtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIHJldHVybiAndGhyZWFkX21heF92ZWN0b3InO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgcmV0dXJuICdtYXgodGhyZWFkX21heF92ZWN0b3IueCwgdGhyZWFkX21heF92ZWN0b3IueSknO1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgcmV0dXJuICdtYXgobWF4KHRocmVhZF9tYXhfdmVjdG9yLngsIHRocmVhZF9tYXhfdmVjdG9yLnkpLCBtYXgodGhyZWFkX21heF92ZWN0b3IueiwgdGhyZWFkX21heF92ZWN0b3IudykpJztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGNvbXBvbmVudHM6ICR7Y29tcG9uZW50c31gKTtcbiAgICAgIH1cbiAgICB9KSgpfTtcbiAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICB2YXIgbWF4X3ZhbHVlID0gIGYzMigtMy40MDI4MjNlKzM4Zik7XG4gICAgZm9yICh2YXIgaSA9IDB1OyBpIDwgJHtXR307IGkrKykge1xuICAgICAgbWF4X3ZhbHVlID0gbWF4KHRocmVhZF9tYXhbaV0sIG1heF92YWx1ZSk7XG4gICAgfVxuXG4gICAgdmFyIHN1bV92ZWN0b3IgPSAke2YzMlR5cGV9KDApO1xuICAgIGZvciAodmFyIGk6IHUzMiA9IDA7IGkgPCB1bmlmb3Jtcy5lbGVtZW50c19wZXJfdGhyZWFkICYmIGkgKyBsb2NhbF9vZmZzZXQgPCBzZXFfY2F1c2FsX2xlbmd0aDsgaSsrKSB7XG4gICAgICBzdW1fdmVjdG9yICs9IGV4cCgke2YzMlR5cGV9KHhbb2Zmc2V0ICsgaV0pIC0gbWF4X3ZhbHVlKTtcbiAgICB9XG4gICAgdGhyZWFkX3N1bVtsb2NhbF9pZHhdID0gJHsoKCkgPT4ge1xuICAgICAgc3dpdGNoIChjb21wb25lbnRzKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICByZXR1cm4gJ3N1bV92ZWN0b3InO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgcmV0dXJuICdzdW1fdmVjdG9yLnggKyBzdW1fdmVjdG9yLnknO1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgcmV0dXJuICdzdW1fdmVjdG9yLnggKyBzdW1fdmVjdG9yLnkgKyBzdW1fdmVjdG9yLnogKyBzdW1fdmVjdG9yLncnO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgY29tcG9uZW50czogJHtjb21wb25lbnRzfWApO1xuICAgICAgfVxuICAgIH0pKCl9O1xuICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgIHZhciBzdW06IGYzMiA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDB1OyBpIDwgJHtXR307IGkrKykge1xuICAgICAgc3VtICs9IHRocmVhZF9zdW1baV07XG4gICAgfVxuXG4gICAgaWYgKHN1bSA9PSAwKSB7XG4gICAgICBmb3IgKHZhciBpOiB1MzIgPSAwOyBpIDwgdW5pZm9ybXMuZWxlbWVudHNfcGVyX3RocmVhZCAmJiBpICsgbG9jYWxfb2Zmc2V0IDwgc2VxX2NhdXNhbF9sZW5ndGg7IGkrKykge1xuICAgICAgICB4W29mZnNldCArIGldID0gJHtpbnB1dEhlbHBlci50eXBlLnZhbHVlfSgke2VsZW1WYWx1ZVR5cGV9KDEuMCkgLyAke2VsZW1WYWx1ZVR5cGV9KHNlcV9jYXVzYWxfbGVuZ3RoKSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAodmFyIGk6IHUzMiA9IDA7IGkgPCB1bmlmb3Jtcy5lbGVtZW50c19wZXJfdGhyZWFkICYmIGkgKyBsb2NhbF9vZmZzZXQgPCBzZXFfY2F1c2FsX2xlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBmMzJpbnB1dCA9ICR7ZjMyVHlwZX0oeFtvZmZzZXQgKyBpXSk7XG4gICAgICAgIHhbb2Zmc2V0ICsgaV0gPSAke2lucHV0SGVscGVyLnR5cGUudmFsdWV9KGV4cChmMzJpbnB1dCAtIG1heF92YWx1ZSkgLyBzdW0pO1xuICAgICAgfVxuICAgIH1cbiAgICAgICR7XG4gICAgICAgIHNlcUxlbnNcbiAgICAgICAgICA/IGBcbiAgICAgICAgZm9yICh2YXIgdG90YWxfc2VxX2lkOiB1MzIgPSBzZXFfY2F1c2FsX2xlbmd0aDsgdG90YWxfc2VxX2lkICsgbG9jYWxfb2Zmc2V0IDwgdW5pZm9ybXMudG90YWxfc2VxdWVuY2VfbGVuZ3RoOyB0b3RhbF9zZXFfaWQrKykge1xuICAgICAgICAgIHhbb2Zmc2V0ICsgdG90YWxfc2VxX2lkXSA9ICR7aW5wdXRIZWxwZXIudHlwZS52YWx1ZX0oJHtlbGVtVmFsdWVUeXBlfSgwKSk7XG4gICAgICAgIH1gXG4gICAgICAgICAgOiAnJ1xuICAgICAgfTtcbiAgfWA7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQXR0ZW50aW9uUHJvYnNTb2Z0bWF4JyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtXR307JHtkYXRhVHlwZX07JHtjb21wb25lbnRzfWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbXSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogMSwgeTogc2VxdWVuY2VMZW5ndGgsIHo6IGJhdGNoU2l6ZSAqIG51bUhlYWRzIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gIH07XG59O1xuXG5jb25zdCBjcmVhdGVBdHRlbnRpb25Qcm9ic1Byb2dyYW1JbmZvID0gKFxuICBvdXRwdXRDb3VudDogbnVtYmVyLFxuICBxOiBUZW5zb3JWaWV3LFxuICBrZXk6IFRlbnNvclZpZXcsXG4gIHBhc3RLZXk6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQsXG4gIGF0dGVudGlvbkJpYXM6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQsXG4gIHBhcmFtZXRlcnM6IEF0dGVudGlvblBhcmFtZXRlcnMsXG4gIHBhc3RTZXF1ZW5jZUxlbmd0aDogbnVtYmVyLFxuICBzZXFMZW5zOiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuICB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQ6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQsXG4pID0+IHtcbiAgY29uc3QgdG90YWxTZXF1ZW5jZUxlbmd0aCA9IHBhc3RTZXF1ZW5jZUxlbmd0aCArIHBhcmFtZXRlcnMua3ZTZXF1ZW5jZUxlbmd0aDtcbiAgY29uc3QgcHJvYnNTaGFwZSA9IFtwYXJhbWV0ZXJzLmJhdGNoU2l6ZSwgcGFyYW1ldGVycy5udW1IZWFkcywgcGFyYW1ldGVycy5zZXF1ZW5jZUxlbmd0aCwgdG90YWxTZXF1ZW5jZUxlbmd0aF07XG4gIGNvbnN0IHByZXNlbnRLZXkgPSBvdXRwdXRDb3VudCA+IDEgJiYgcGFzdEtleTtcbiAgY29uc3Qga3ZOdW1IZWFkcyA9IHBhcmFtZXRlcnMua3ZOdW1IZWFkcyA/IHBhcmFtZXRlcnMua3ZOdW1IZWFkcyA6IHBhcmFtZXRlcnMubnVtSGVhZHM7XG4gIGNvbnN0IHByZXNlbnRLZXlTaGFwZSA9IHByZXNlbnRLZXlcbiAgICA/IFtwYXJhbWV0ZXJzLmJhdGNoU2l6ZSwga3ZOdW1IZWFkcywgdG90YWxTZXF1ZW5jZUxlbmd0aCwgcGFyYW1ldGVycy5oZWFkU2l6ZV1cbiAgICA6IHVuZGVmaW5lZDtcbiAgY29uc3QgblJlcHMgPSBwYXJhbWV0ZXJzLm5SZXBzID8gcGFyYW1ldGVycy5uUmVwcyA6IDE7XG4gIC8vIFRPRE86IGhhbmRsZSBtYXNrXG5cbiAgY29uc3QgYWxwaGEgPSBwYXJhbWV0ZXJzLnNjYWxlID09PSAwID8gMS4wIC8gTWF0aC5zcXJ0KHBhcmFtZXRlcnMuaGVhZFNpemUpIDogcGFyYW1ldGVycy5zY2FsZTtcbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMocGFyYW1ldGVycy5oZWFkU2l6ZSk7XG4gIGNvbnN0IHZlY3Rvcml6ZWRIZWFkU2l6ZSA9IHBhcmFtZXRlcnMuaGVhZFNpemUgLyBjb21wb25lbnRzO1xuICBjb25zdCBUSUxFX1NJWkUgPSAxMjtcbiAgY29uc3QgZGlzcGF0Y2ggPSB7XG4gICAgeDogTWF0aC5jZWlsKHRvdGFsU2VxdWVuY2VMZW5ndGggLyBUSUxFX1NJWkUpLFxuICAgIHk6IE1hdGguY2VpbChwYXJhbWV0ZXJzLnNlcXVlbmNlTGVuZ3RoIC8gVElMRV9TSVpFKSxcbiAgICB6OiBwYXJhbWV0ZXJzLmJhdGNoU2l6ZSAqIHBhcmFtZXRlcnMubnVtSGVhZHMsXG4gIH07XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1ldGVycy5zZXF1ZW5jZUxlbmd0aCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiB2ZWN0b3JpemVkSGVhZFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogdG90YWxTZXF1ZW5jZUxlbmd0aCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbWV0ZXJzLm51bUhlYWRzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhcmFtZXRlcnMuaGVhZFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBhbHBoYSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXN0U2VxdWVuY2VMZW5ndGggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1ldGVycy5rdlNlcXVlbmNlTGVuZ3RoIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG5SZXBzIH0sXG4gIF07XG4gIC8vIEZlZWQgcGFzdEtleSB0byB0aGUgc2hhZGVyLWNvZGUgb25seSBpZiBpdCBpcyBub24temVybyBhbmQgcHJlc2VudEtleSBpcyBiZWluZyBwcm9kdWNlZFxuICBjb25zdCBmZWVkUGFzdEtleSA9IHByZXNlbnRLZXkgJiYgcGFzdEtleSAmJiBTaGFwZVV0aWwuc2l6ZShwYXN0S2V5LmRpbXMpID4gMDtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3R5cGUnLCAndHlwZSddO1xuICBpZiAoZmVlZFBhc3RLZXkpIHtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCd0eXBlJyk7XG4gIH1cbiAgaWYgKGF0dGVudGlvbkJpYXMpIHtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCd0eXBlJyk7XG4gIH1cbiAgaWYgKHNlcUxlbnMpIHtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCd0eXBlJyk7XG4gIH1cbiAgaWYgKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCkge1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3R5cGUnKTtcbiAgfVxuICBjb25zdCBvdXRwdXRzID0gW3sgZGltczogcHJvYnNTaGFwZSwgZGF0YVR5cGU6IHEuZGF0YVR5cGUsIGdwdURhdGFUeXBlOiBHcHVEYXRhVHlwZS5kZWZhdWx0IH1dO1xuICBpZiAocHJlc2VudEtleSkge1xuICAgIG91dHB1dHMucHVzaCh7IGRpbXM6IHByZXNlbnRLZXlTaGFwZSEsIGRhdGFUeXBlOiBxLmRhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCB9KTtcbiAgfVxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBxSW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdxJywgcS5kYXRhVHlwZSwgcS5kaW1zLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBrSW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdrZXknLCBrZXkuZGF0YVR5cGUsIGtleS5kaW1zLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBpbnB1dFZhcnMgPSBbcUlucHV0LCBrSW5wdXRdO1xuICAgIGlmIChmZWVkUGFzdEtleSkge1xuICAgICAgY29uc3QgcGFzdEtleUlucHV0ID0gaW5wdXRWYXJpYWJsZSgncGFzdF9rZXknLCBwYXN0S2V5LmRhdGFUeXBlLCBwYXN0S2V5LmRpbXMsIGNvbXBvbmVudHMpO1xuICAgICAgaW5wdXRWYXJzLnB1c2gocGFzdEtleUlucHV0KTtcbiAgICB9XG4gICAgaWYgKGF0dGVudGlvbkJpYXMpIHtcbiAgICAgIGlucHV0VmFycy5wdXNoKGlucHV0VmFyaWFibGUoJ2F0dGVudGlvbl9iaWFzJywgYXR0ZW50aW9uQmlhcy5kYXRhVHlwZSwgYXR0ZW50aW9uQmlhcy5kaW1zKSk7XG4gICAgfVxuICAgIGNvbnN0IHNlcUxlbnNJbnB1dFZhcmlhYmxlID0gc2VxTGVucyA/IGlucHV0VmFyaWFibGUoJ3NlcV9sZW5zJywgc2VxTGVucy5kYXRhVHlwZSwgc2VxTGVucy5kaW1zKSA6IHVuZGVmaW5lZDtcbiAgICBpZiAoc2VxTGVuc0lucHV0VmFyaWFibGUpIHtcbiAgICAgIGlucHV0VmFycy5wdXNoKHNlcUxlbnNJbnB1dFZhcmlhYmxlKTtcbiAgICB9XG4gICAgY29uc3QgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0VmFyaWFibGUgPSB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXRcbiAgICAgID8gaW5wdXRWYXJpYWJsZSgndG90YWxfc2VxdWVuY2VfbGVuZ3RoX2lucHV0JywgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0LmRhdGFUeXBlLCB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQuZGltcylcbiAgICAgIDogdW5kZWZpbmVkO1xuICAgIGlmICh0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXRWYXJpYWJsZSkge1xuICAgICAgaW5wdXRWYXJzLnB1c2godG90YWxTZXF1ZW5jZUxlbmd0aElucHV0VmFyaWFibGUpO1xuICAgIH1cbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgcS5kYXRhVHlwZSwgcHJvYnNTaGFwZSk7XG4gICAgY29uc3Qgb3V0cHV0VmFycyA9IFtvdXRwdXRdO1xuICAgIGlmIChwcmVzZW50S2V5KSB7XG4gICAgICBvdXRwdXRWYXJzLnB1c2gob3V0cHV0VmFyaWFibGUoJ3ByZXNlbnRfa2V5JywgcS5kYXRhVHlwZSwgcHJlc2VudEtleVNoYXBlISwgY29tcG9uZW50cykpO1xuICAgIH1cbiAgICBjb25zdCBmMzJUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShEYXRhVHlwZS5mbG9hdCwgY29tcG9uZW50cyk7XG5cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdNJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ0snLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnTicsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdudW1faGVhZHMnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnaGVhZF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2FscGhhJywgdHlwZTogJ2YzMicgYXMgVW5pZm9ybURhdGFFbGVtZW50VHlwZSB9LFxuICAgICAgeyBuYW1lOiAncGFzdF9zZXF1ZW5jZV9sZW5ndGgnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAna3Zfc2VxdWVuY2VfbGVuZ3RoJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ25fcmVwcycsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcbiAgICByZXR1cm4gYFxuICBjb25zdCBUSUxFX1NJWkUgPSAke1RJTEVfU0laRX11O1xuXG4gIHZhcjx3b3JrZ3JvdXA+IHRpbGVROiBhcnJheTwke3FJbnB1dC50eXBlLnN0b3JhZ2V9LCAke1RJTEVfU0laRSAqIFRJTEVfU0laRX0+O1xuICB2YXI8d29ya2dyb3VwPiB0aWxlSzogYXJyYXk8JHtxSW5wdXQudHlwZS5zdG9yYWdlfSwgJHtUSUxFX1NJWkUgKiBUSUxFX1NJWkV9PjtcbiAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcnMsIC4uLm91dHB1dFZhcnMpfVxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoW1RJTEVfU0laRSwgVElMRV9TSVpFLCAxXSl9XG4gICAgLy8geCBob2xkcyB0aGUgTiBhbmQgeSBob2xkcyB0aGUgTVxuICAgIGxldCBoZWFkSWR4ID0gd29ya2dyb3VwX2lkLnogJSB1bmlmb3Jtcy5udW1faGVhZHM7XG4gICAgbGV0IGt2SGVhZElkeCA9ICR7blJlcHMgPT09IDEgPyAnaGVhZElkeCcgOiAnaGVhZElkeCAvIHVuaWZvcm1zLm5fcmVwcyd9O1xuICAgIGxldCBrdl9udW1faGVhZHMgPSAke25SZXBzID09PSAxID8gJ3VuaWZvcm1zLm51bV9oZWFkcycgOiAndW5pZm9ybXMubnVtX2hlYWRzIC8gdW5pZm9ybXMubl9yZXBzJ307XG4gICAgbGV0IGJhdGNoSWR4ID0gd29ya2dyb3VwX2lkLnogLyB1bmlmb3Jtcy5udW1faGVhZHM7XG4gICAgbGV0IG0gPSB3b3JrZ3JvdXBfaWQueSAqIFRJTEVfU0laRTtcbiAgICBsZXQgbiA9IHdvcmtncm91cF9pZC54ICogVElMRV9TSVpFO1xuICAgIGxldCBzZXF1ZW5jZV9sZW5ndGggPSB1bmlmb3Jtcy5NO1xuICAgIHZhciB0b3RhbF9zZXF1ZW5jZV9sZW5ndGggPSB1bmlmb3Jtcy5OO1xuICAgICR7aW5pdFZhclN0dWIoc2VxTGVuc0lucHV0VmFyaWFibGUsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dFZhcmlhYmxlLCB0cnVlKX1cbiAgICBsZXQgYWJzS3ZIZWFkSWR4ID0gYmF0Y2hJZHggKiBrdl9udW1faGVhZHMgKyBrdkhlYWRJZHg7XG4gICAgbGV0IHFPZmZzZXQgPSB3b3JrZ3JvdXBfaWQueiAqIHVuaWZvcm1zLk0gKiB1bmlmb3Jtcy5LICsgbSAqIHVuaWZvcm1zLks7XG4gICAgJHtmZWVkUGFzdEtleSAmJiBwcmVzZW50S2V5ID8gJ2xldCBwYXN0S2V5T2Zmc2V0ID0gYWJzS3ZIZWFkSWR4ICogdW5pZm9ybXMucGFzdF9zZXF1ZW5jZV9sZW5ndGggKiB1bmlmb3Jtcy5LOycgOiAnJ307XG4gICAgbGV0IGtPZmZzZXQgPSBhYnNLdkhlYWRJZHggKiB1bmlmb3Jtcy5rdl9zZXF1ZW5jZV9sZW5ndGggKiB1bmlmb3Jtcy5LO1xuICAgICR7cHJlc2VudEtleSA/ICdsZXQgcHJlc2VudEtleU9mZnNldCA9IGFic0t2SGVhZElkeCAqIHVuaWZvcm1zLk4gKiB1bmlmb3Jtcy5LOycgOiAnJ31cbiAgICB2YXIgdmFsdWUgPSAke2YzMlR5cGV9KDApO1xuICAgIGZvciAodmFyIHc6IHUzMiA9IDB1OyB3IDwgdW5pZm9ybXMuSzsgdyArPSBUSUxFX1NJWkUpIHtcbiAgICAgIGlmIChnbG9iYWxfaWQueSA8IHVuaWZvcm1zLk0gJiYgdyArIGxvY2FsX2lkLnggPCB1bmlmb3Jtcy5LKSB7XG4gICAgICAgIHRpbGVRW1RJTEVfU0laRSAqIGxvY2FsX2lkLnkgKyBsb2NhbF9pZC54XSA9IHFbcU9mZnNldCArIGxvY2FsX2lkLnkgKiB1bmlmb3Jtcy5LICsgdyArIGxvY2FsX2lkLnhdO1xuICAgICAgfVxuICAgICAgaWYgKG4gKyBsb2NhbF9pZC55IDwgdW5pZm9ybXMuTiAmJiB3ICsgbG9jYWxfaWQueCA8IHVuaWZvcm1zLkspIHtcbiAgICAgICAgdmFyIGlkeCA9IFRJTEVfU0laRSAqIGxvY2FsX2lkLnkgKyBsb2NhbF9pZC54O1xuICAgICAgJHsoKCkgPT4ge1xuICAgICAgICBpZiAoZmVlZFBhc3RLZXkgJiYgcHJlc2VudEtleSkge1xuICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICAgIGlmIChuICsgbG9jYWxfaWQueSA8IHBhc3Rfc2VxdWVuY2VfbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGlsZUtbaWR4XSA9IHBhc3Rfa2V5W3Bhc3RLZXlPZmZzZXQgKyAobiArIGxvY2FsX2lkLnkpICogdW5pZm9ybXMuSyArIHcgKyBsb2NhbF9pZC54XTtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmIChuICsgbG9jYWxfaWQueSAtIHBhc3Rfc2VxdWVuY2VfbGVuZ3RoIDwgdW5pZm9ybXMua3Zfc2VxdWVuY2VfbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGlsZUtbaWR4XSA9IGtleVtrT2Zmc2V0ICsgKG4gKyBsb2NhbF9pZC55IC0gcGFzdF9zZXF1ZW5jZV9sZW5ndGgpICogdW5pZm9ybXMuSyArIHcgKyBsb2NhbF9pZC54XTtcbiAgICAgICAgICAgICAgfWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICBpZiAobiArIGxvY2FsX2lkLnkgPCB1bmlmb3Jtcy5rdl9zZXF1ZW5jZV9sZW5ndGgpIHtcbiAgICAgICAgICAgIHRpbGVLW2lkeF0gPSBrZXlba09mZnNldCArIChuICsgbG9jYWxfaWQueSkgKiB1bmlmb3Jtcy5LICsgdyArIGxvY2FsX2lkLnhdO1xuICAgICAgICAgIH1gO1xuICAgICAgICB9XG4gICAgICB9KSgpfVxuICAgICAgJHtcbiAgICAgICAgcHJlc2VudEtleVxuICAgICAgICAgID8gYGlmIChuICsgbG9jYWxfaWQueSA8IHByZXNlbnRfc2VxdWVuY2VfbGVuZ3RoKSB7XG4gICAgICAgIHByZXNlbnRfa2V5W3ByZXNlbnRLZXlPZmZzZXQgKyAobiArIGxvY2FsX2lkLnkpICogdW5pZm9ybXMuSyArIHcgKyBsb2NhbF9pZC54XSA9IHRpbGVLW2lkeF07XG4gICAgICB9YFxuICAgICAgICAgIDogJydcbiAgICAgIH1cbiAgICAgIH1cbiAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgZm9yICh2YXIgazogdTMyID0gMHU7IGsgPCBUSUxFX1NJWkUgJiYgdytrIDwgdW5pZm9ybXMuSzsgaysrKSB7XG4gICAgICAgICAgdmFsdWUgKz0gJHtmMzJUeXBlfSh0aWxlUVtUSUxFX1NJWkUgKiBsb2NhbF9pZC55ICsga10gKiB0aWxlS1tUSUxFX1NJWkUgKiBsb2NhbF9pZC54ICsga10pO1xuICAgICAgfVxuXG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgfVxuXG4gICAgaWYgKGdsb2JhbF9pZC55IDwgdW5pZm9ybXMuTSAmJiBnbG9iYWxfaWQueCA8IHRvdGFsX3NlcXVlbmNlX2xlbmd0aCkge1xuICAgICAgbGV0IGhlYWRPZmZzZXQgPSB3b3JrZ3JvdXBfaWQueiAqIHVuaWZvcm1zLk0gKiB1bmlmb3Jtcy5OO1xuICAgICAgbGV0IG91dHB1dElkeCA9IGhlYWRPZmZzZXQgKyBnbG9iYWxfaWQueSAqIHVuaWZvcm1zLk4gKyBnbG9iYWxfaWQueDtcbiAgICAgIHZhciBzdW06IGYzMiA9ICR7KCgpID0+IHtcbiAgICAgICAgc3dpdGNoIChjb21wb25lbnRzKSB7XG4gICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgcmV0dXJuICd2YWx1ZSc7XG4gICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgcmV0dXJuICd2YWx1ZS54ICsgdmFsdWUueSc7XG4gICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgcmV0dXJuICd2YWx1ZS54ICsgdmFsdWUueSArIHZhbHVlLnogKyB2YWx1ZS53JztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBjb21wb25lbnRzOiAke2NvbXBvbmVudHN9YCk7XG4gICAgICAgIH1cbiAgICAgIH0pKCl9O1xuICAgICAgICBvdXRwdXRbb3V0cHV0SWR4XSA9ICR7b3V0cHV0LnR5cGUudmFsdWV9IChzdW0gKiB1bmlmb3Jtcy5hbHBoYSkgKyAke1xuICAgICAgICAgIGF0dGVudGlvbkJpYXMgPyAnYXR0ZW50aW9uX2JpYXNbb3V0cHV0SWR4XScgOiAnMC4wJ1xuICAgICAgICB9O1xuICAgIH1cbiAgfWA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0F0dGVudGlvblByb2JzJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7Y29tcG9uZW50c307JHthdHRlbnRpb25CaWFzICE9PSB1bmRlZmluZWR9OyR7cGFzdEtleSAhPT0gdW5kZWZpbmVkfTske291dHB1dENvdW50fWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llcyxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7IG91dHB1dHMsIGRpc3BhdGNoR3JvdXA6IGRpc3BhdGNoLCBwcm9ncmFtVW5pZm9ybXMgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuY29uc3QgY3JlYXRlVnhBdHRlbnRpb25TY29yZVByb2dyYW1JbmZvID0gKFxuICBvdXRwdXRDb3VudDogbnVtYmVyLFxuICBwcm9iczogVGVuc29yVmlldyxcbiAgdjogVGVuc29yVmlldyxcbiAgcGFzdFZhbHVlOiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuICBwYXJhbXM6IEF0dGVudGlvblBhcmFtZXRlcnMsXG4gIHBhc3RTZXF1ZW5jZUxlbmd0aDogbnVtYmVyLFxuICBzZXFMZW5zOiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkLFxuICB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQ6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQsXG4pID0+IHtcbiAgY29uc3QgdG90YWxTZXF1ZW5jZUxlbmd0aCA9IHBhc3RTZXF1ZW5jZUxlbmd0aCArIHBhcmFtcy5rdlNlcXVlbmNlTGVuZ3RoO1xuICBjb25zdCBuUmVwcyA9IHBhcmFtcy5uUmVwcyA/IHBhcmFtcy5uUmVwcyA6IDE7XG4gIGNvbnN0IHJlcGVhdGVkVkhpZGRlblNpemUgPSBwYXJhbXMudkhpZGRlblNpemUgKiBuUmVwcztcbiAgY29uc3QgcHJlc2VudFZhbHVlID0gb3V0cHV0Q291bnQgPiAxICYmIHBhc3RWYWx1ZTtcbiAgY29uc3Qga3ZOdW1IZWFkcyA9IHBhcmFtcy5rdk51bUhlYWRzID8gcGFyYW1zLmt2TnVtSGVhZHMgOiBwYXJhbXMubnVtSGVhZHM7XG4gIGNvbnN0IHByZXNlbnRWYWx1ZVNoYXBlID0gcHJlc2VudFZhbHVlXG4gICAgPyBbcGFyYW1zLmJhdGNoU2l6ZSwga3ZOdW1IZWFkcywgdG90YWxTZXF1ZW5jZUxlbmd0aCwgcGFyYW1zLmhlYWRTaXplXVxuICAgIDogdW5kZWZpbmVkO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IFtwYXJhbXMuYmF0Y2hTaXplLCBwYXJhbXMuc2VxdWVuY2VMZW5ndGgsIHJlcGVhdGVkVkhpZGRlblNpemVdO1xuICBjb25zdCBUSUxFX1NJWkUgPSAxMjtcbiAgY29uc3QgZGlzcGF0Y2ggPSB7XG4gICAgeDogTWF0aC5jZWlsKHBhcmFtcy52SGVhZFNpemUgLyBUSUxFX1NJWkUpLFxuICAgIHk6IE1hdGguY2VpbChwYXJhbXMuc2VxdWVuY2VMZW5ndGggLyBUSUxFX1NJWkUpLFxuICAgIHo6IHBhcmFtcy5iYXRjaFNpemUgKiBwYXJhbXMubnVtSGVhZHMsXG4gIH07XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbXMuc2VxdWVuY2VMZW5ndGggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogdG90YWxTZXF1ZW5jZUxlbmd0aCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbXMudkhlYWRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhcmFtcy5udW1IZWFkcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbXMuaGVhZFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcmVwZWF0ZWRWSGlkZGVuU2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXN0U2VxdWVuY2VMZW5ndGggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1zLmt2U2VxdWVuY2VMZW5ndGggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogblJlcHMgfSxcbiAgXTtcbiAgLy8gRmVlZCBwYXN0VmFsdWUgdG8gdGhlIHNoYWRlci1jb2RlIG9ubHkgaWYgaXQgaXMgbm9uLWVtcHR5IGFuZCBwcmVzZW50VmFsdWUgaXMgYmVpbmcgcHJvZHVjZWRcbiAgY29uc3QgZmVlZFBhc3RWYWx1ZSA9IHByZXNlbnRWYWx1ZSAmJiBwYXN0VmFsdWUgJiYgU2hhcGVVdGlsLnNpemUocGFzdFZhbHVlLmRpbXMpID4gMDtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3R5cGUnLCAndHlwZSddO1xuICBpZiAoZmVlZFBhc3RWYWx1ZSkge1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3R5cGUnKTtcbiAgfVxuICBpZiAoc2VxTGVucykge1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3R5cGUnKTtcbiAgfVxuICBpZiAodG90YWxTZXF1ZW5jZUxlbmd0aElucHV0KSB7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgndHlwZScpO1xuICB9XG4gIGNvbnN0IG91dHB1dHMgPSBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IHByb2JzLmRhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCB9XTtcbiAgaWYgKHByZXNlbnRWYWx1ZSkge1xuICAgIG91dHB1dHMucHVzaCh7IGRpbXM6IHByZXNlbnRWYWx1ZVNoYXBlISwgZGF0YVR5cGU6IHByb2JzLmRhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCB9KTtcbiAgfVxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBwcm9ic0hlbHBlciA9IGlucHV0VmFyaWFibGUoJ3Byb2JzJywgcHJvYnMuZGF0YVR5cGUsIHByb2JzLmRpbXMpO1xuICAgIGNvbnN0IHZIZWxwZXIgPSBpbnB1dFZhcmlhYmxlKCd2Jywgdi5kYXRhVHlwZSwgdi5kaW1zKTtcbiAgICBjb25zdCBpbnB1dFZhcnMgPSBbcHJvYnNIZWxwZXIsIHZIZWxwZXJdO1xuICAgIGlmIChmZWVkUGFzdFZhbHVlKSB7XG4gICAgICBpbnB1dFZhcnMucHVzaChpbnB1dFZhcmlhYmxlKCdwYXN0X3ZhbHVlJywgcGFzdFZhbHVlLmRhdGFUeXBlLCBwYXN0VmFsdWUuZGltcykpO1xuICAgIH1cbiAgICBjb25zdCBzZXFMZW5zSW5wdXRWYXJpYWJsZSA9IHNlcUxlbnMgPyBpbnB1dFZhcmlhYmxlKCdzZXFfbGVucycsIHNlcUxlbnMuZGF0YVR5cGUsIHNlcUxlbnMuZGltcykgOiB1bmRlZmluZWQ7XG4gICAgaWYgKHNlcUxlbnMpIHtcbiAgICAgIGlucHV0VmFycy5wdXNoKHNlcUxlbnNJbnB1dFZhcmlhYmxlISk7XG4gICAgfVxuICAgIGNvbnN0IHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dFZhcmlhYmxlID0gdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0XG4gICAgICA/IGlucHV0VmFyaWFibGUoJ3RvdGFsX3NlcXVlbmNlX2xlbmd0aF9pbnB1dCcsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dC5kYXRhVHlwZSwgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0LmRpbXMpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgICBpZiAodG90YWxTZXF1ZW5jZUxlbmd0aElucHV0KSB7XG4gICAgICBpbnB1dFZhcnMucHVzaCh0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXRWYXJpYWJsZSEpO1xuICAgIH1cbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgcHJvYnMuZGF0YVR5cGUsIG91dHB1dFNoYXBlKTtcbiAgICBjb25zdCBvdXRwdXRWYXJzID0gW291dHB1dF07XG4gICAgaWYgKHByZXNlbnRWYWx1ZSkge1xuICAgICAgb3V0cHV0VmFycy5wdXNoKG91dHB1dFZhcmlhYmxlKCdwcmVzZW50X3ZhbHVlJywgcHJvYnMuZGF0YVR5cGUsIHByZXNlbnRWYWx1ZVNoYXBlISkpO1xuICAgIH1cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdNJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ0snLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnTicsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdudW1faGVhZHMnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnaGVhZF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3ZfaGlkZGVuX3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAncGFzdF9zZXF1ZW5jZV9sZW5ndGgnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAna3Zfc2VxdWVuY2VfbGVuZ3RoJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ25fcmVwcycsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcbiAgICByZXR1cm4gYFxuICBjb25zdCBUSUxFX1NJWkUgPSAke1RJTEVfU0laRX11O1xuICB2YXI8d29ya2dyb3VwPiB0aWxlUTogYXJyYXk8JHtwcm9ic0hlbHBlci50eXBlLnZhbHVlfSwgJHtUSUxFX1NJWkUgKiBUSUxFX1NJWkV9PjtcbiAgdmFyPHdvcmtncm91cD4gdGlsZVY6IGFycmF5PCR7cHJvYnNIZWxwZXIudHlwZS52YWx1ZX0sICR7VElMRV9TSVpFICogVElMRV9TSVpFfT47XG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJzLCAuLi5vdXRwdXRWYXJzKX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KFtUSUxFX1NJWkUsIFRJTEVfU0laRSwgMV0pfVxuICAgbGV0IGhlYWRJZHggPSB3b3JrZ3JvdXBfaWQueiAlIHVuaWZvcm1zLm51bV9oZWFkcztcbiAgIGxldCBiYXRjaElkeCA9IHdvcmtncm91cF9pZC56IC8gdW5pZm9ybXMubnVtX2hlYWRzO1xuICAgbGV0IGt2SGVhZElkeCA9ICR7blJlcHMgPT09IDEgPyAnaGVhZElkeCcgOiAnaGVhZElkeCAvIHVuaWZvcm1zLm5fcmVwcyd9O1xuICAgbGV0IGt2X251bV9oZWFkcyA9ICR7blJlcHMgPT09IDEgPyAndW5pZm9ybXMubnVtX2hlYWRzJyA6ICd1bmlmb3Jtcy5udW1faGVhZHMgLyB1bmlmb3Jtcy5uX3JlcHMnfTtcbiAgIGxldCBtID0gZ2xvYmFsX2lkLnk7XG4gICBsZXQgbiA9IGdsb2JhbF9pZC54O1xuICAgbGV0IHNlcXVlbmNlX2xlbmd0aCA9IHVuaWZvcm1zLk07XG4gICB2YXIgdG90YWxfc2VxdWVuY2VfbGVuZ3RoID0gdW5pZm9ybXMuSztcbiAgICR7aW5pdFZhclN0dWIoc2VxTGVuc0lucHV0VmFyaWFibGUsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dFZhcmlhYmxlLCB0cnVlKX1cbiAgIGxldCBvZmZzZXRBID0gd29ya2dyb3VwX2lkLnogKiB1bmlmb3Jtcy5NICogdW5pZm9ybXMuSyArIG0gKiB1bmlmb3Jtcy5LO1xuICAgbGV0IGFic0t2SGVhZElkeCA9IGJhdGNoSWR4ICoga3ZfbnVtX2hlYWRzICsga3ZIZWFkSWR4OyAvLyBrdkhlYWRJZHggaXMgcmVsYXRpdmUgdG8gdGhlIGJhdGNoXG4gICAke2ZlZWRQYXN0VmFsdWUgJiYgcHJlc2VudFZhbHVlID8gJ2xldCBwYXN0VmFsdWVPZmZzZXQgPSBhYnNLdkhlYWRJZHggKiB1bmlmb3Jtcy5OICogdW5pZm9ybXMucGFzdF9zZXF1ZW5jZV9sZW5ndGggKyBuOycgOiAnJ307XG4gICBsZXQgdk9mZnNldCA9IGFic0t2SGVhZElkeCAqIHVuaWZvcm1zLk4gKiB1bmlmb3Jtcy5rdl9zZXF1ZW5jZV9sZW5ndGggKyBuO1xuICAgJHtwcmVzZW50VmFsdWUgPyAnbGV0IHByZXNlbnRWYWx1ZU9mZnNldCA9IGFic0t2SGVhZElkeCAqIHVuaWZvcm1zLk4gKiB1bmlmb3Jtcy5LICsgbjsnIDogJyd9XG4gICB2YXIgdmFsdWUgPSAke3Byb2JzSGVscGVyLnR5cGUuc3RvcmFnZX0oMCk7XG4gICBmb3IgKHZhciB3OiB1MzIgPSAwdTsgdyA8IHVuaWZvcm1zLks7IHcgKz0gVElMRV9TSVpFKSB7XG4gICAgICBpZiAobSA8IHVuaWZvcm1zLk0gJiYgdyArIGxvY2FsX2lkLnggPCB1bmlmb3Jtcy5LKSB7XG4gICAgICAgIHRpbGVRW1RJTEVfU0laRSAqIGxvY2FsX2lkLnkgKyBsb2NhbF9pZC54XSA9IHByb2JzW29mZnNldEEgKyB3ICsgbG9jYWxfaWQueF07XG4gICAgICB9XG4gICAgICBpZiAobiA8IHVuaWZvcm1zLk4gJiYgdyArIGxvY2FsX2lkLnkgPCB1bmlmb3Jtcy5LKSB7XG4gICAgICAgIHZhciBpZHggPSBUSUxFX1NJWkUgKiBsb2NhbF9pZC55ICsgbG9jYWxfaWQueDtcbiAgICAgICAgJHsoKCkgPT4ge1xuICAgICAgICAgIGlmIChmZWVkUGFzdFZhbHVlICYmIHByZXNlbnRWYWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgaWYgKHcgKyBsb2NhbF9pZC55IDwgcGFzdF9zZXF1ZW5jZV9sZW5ndGgpIHtcbiAgICAgICAgICB0aWxlVltpZHhdID0gcGFzdF92YWx1ZVtwYXN0VmFsdWVPZmZzZXQgKyAodyArIGxvY2FsX2lkLnkpICogdW5pZm9ybXMuTl07XG4gICAgICAgIH0gZWxzZSBpZiAodyArIGxvY2FsX2lkLnkgLSBwYXN0X3NlcXVlbmNlX2xlbmd0aCA8IHVuaWZvcm1zLmt2X3NlcXVlbmNlX2xlbmd0aCkge1xuICAgICAgICAgIHRpbGVWW2lkeF0gPSB2W3ZPZmZzZXQgKyAodyArIGxvY2FsX2lkLnkgLSBwYXN0X3NlcXVlbmNlX2xlbmd0aCkgKiB1bmlmb3Jtcy5OXTtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICAgIGlmICh3ICsgbG9jYWxfaWQueSA8IHVuaWZvcm1zLmt2X3NlcXVlbmNlX2xlbmd0aCkge1xuICAgICAgICAgICAgICB0aWxlVltpZHhdID0gdlt2T2Zmc2V0ICsgKHcgKyBsb2NhbF9pZC55KSAqIHVuaWZvcm1zLk5dO1xuICAgICAgICAgICAgfWA7XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpfVxuICAgICAgICAke1xuICAgICAgICAgIHByZXNlbnRWYWx1ZVxuICAgICAgICAgICAgPyBgXG4gICAgICAgICAgICBpZiAodyArIGxvY2FsX2lkLnkgPCBwcmVzZW50X3NlcXVlbmNlX2xlbmd0aCkge1xuICAgICAgICAgIHByZXNlbnRfdmFsdWVbcHJlc2VudFZhbHVlT2Zmc2V0ICsgKHcgKyBsb2NhbF9pZC55KSAqIHVuaWZvcm1zLk5dID0gdGlsZVZbaWR4XTtcbiAgICAgICAgfWBcbiAgICAgICAgICAgIDogJydcbiAgICAgICAgfVxuICAgICAgfVxuICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgIGZvciAodmFyIGs6IHUzMiA9IDB1OyBrIDwgVElMRV9TSVpFICYmIHcrayA8IHRvdGFsX3NlcXVlbmNlX2xlbmd0aDsgaysrKSB7XG4gICAgICAgdmFsdWUgKz0gdGlsZVFbVElMRV9TSVpFICogbG9jYWxfaWQueSArIGtdICogdGlsZVZbVElMRV9TSVpFICogayArIGxvY2FsX2lkLnhdO1xuICAgICB9XG4gICAgIHdvcmtncm91cEJhcnJpZXIoKTtcbiAgIH1cblxuICAgLy8gd2UgbmVlZCB0byB0cmFuc3Bvc2Ugb3V0cHV0IGZyb20gQk5TSF92IHRvIEJTTkRfdlxuICAgaWYgKG0gPCB1bmlmb3Jtcy5NICYmIG4gPCB1bmlmb3Jtcy5OKSB7XG4gICAgIGxldCBvdXRwdXRJZHggPSBiYXRjaElkeCAqIHVuaWZvcm1zLk0gKiB1bmlmb3Jtcy52X2hpZGRlbl9zaXplICsgbSAqIHVuaWZvcm1zLnZfaGlkZGVuX3NpemVcbiAgICAgICArIGhlYWRJZHggKiB1bmlmb3Jtcy5OICsgbjtcbiAgICAgb3V0cHV0W291dHB1dElkeF0gPSB2YWx1ZTtcbiAgIH1cbiAgfWA7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQXR0ZW50aW9uU2NvcmUnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke3Bhc3RWYWx1ZSAhPT0gdW5kZWZpbmVkfTske291dHB1dENvdW50fWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHsgb3V0cHV0cywgZGlzcGF0Y2hHcm91cDogZGlzcGF0Y2gsIHByb2dyYW1Vbmlmb3JtcyB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgYXBwbHlBdHRlbnRpb24gPSAoXG4gIGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LFxuICBxOiBUZW5zb3JWaWV3LFxuICBrOiBUZW5zb3JWaWV3LFxuICB2OiBUZW5zb3JWaWV3LFxuICBfbWFza0luZGV4OiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuICBfcGFzdDogVGVuc29yVmlldyB8IHVuZGVmaW5lZCxcbiAgcGFzdEtleTogVGVuc29yVmlldyB8IHVuZGVmaW5lZCxcbiAgcGFzdFZhbHVlOiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkLFxuICBhdHRlbnRpb25CaWFzSW5wdXQ6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQsXG4gIHBhcmFtZXRlcnM6IEF0dGVudGlvblBhcmFtZXRlcnMsXG4gIHNlcUxlbnM6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQsXG4gIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dDogVGVuc29yVmlldyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbikgPT4ge1xuICAvLyBBc3N1bXB0aW9uIGlzIHRoYXQgcHJlc2VudEtleS9wcmVzZW50VmFsdWUgZXhpc3RzIG9ubHkgaWYgcGFzdEtleS9wYXN0VmFsdWUgZXhpc3RzLlxuICBjb25zdCBvdXRwdXRDb3VudCA9IE1hdGgubWluKGNvbnRleHQub3V0cHV0Q291bnQsIDEgKyAocGFzdEtleSA/IDEgOiAwKSArIChwYXN0VmFsdWUgPyAxIDogMCkpO1xuICBjb25zdCBwYXN0U2VxdWVuY2VMZW5ndGggPSBvdXRwdXRDb3VudCA+IDEgPyBwYXJhbWV0ZXJzLnBhc3RTZXF1ZW5jZUxlbmd0aCA6IDA7XG4gIGNvbnN0IHRvdGFsU2VxdWVuY2VMZW5ndGggPSBwYXN0U2VxdWVuY2VMZW5ndGggKyBwYXJhbWV0ZXJzLmt2U2VxdWVuY2VMZW5ndGg7XG4gIGNvbnN0IGF0dGVudGlvbkJpYXMgPVxuICAgIGF0dGVudGlvbkJpYXNJbnB1dCAmJiBTaGFwZVV0aWwuc2l6ZShhdHRlbnRpb25CaWFzSW5wdXQuZGltcykgPiAwID8gYXR0ZW50aW9uQmlhc0lucHV0IDogdW5kZWZpbmVkO1xuXG4gIGNvbnN0IGlucHV0c0sgPSBbcSwga107XG4gIGlmIChvdXRwdXRDb3VudCA+IDEgJiYgcGFzdEtleSAmJiBTaGFwZVV0aWwuc2l6ZShwYXN0S2V5LmRpbXMpID4gMCkge1xuICAgIGlucHV0c0sucHVzaChwYXN0S2V5KTtcbiAgfVxuICBpZiAoYXR0ZW50aW9uQmlhcykge1xuICAgIGlucHV0c0sucHVzaChhdHRlbnRpb25CaWFzKTtcbiAgfVxuICBpZiAoc2VxTGVucykge1xuICAgIGlucHV0c0sucHVzaChzZXFMZW5zKTtcbiAgfVxuICBpZiAodG90YWxTZXF1ZW5jZUxlbmd0aElucHV0KSB7XG4gICAgaW5wdXRzSy5wdXNoKHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCk7XG4gIH1cbiAgLy8gUnVuIEF0dGVudGlvblByb2JzXG4gIGNvbnN0IHByb2JzID0gY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUF0dGVudGlvblByb2JzUHJvZ3JhbUluZm8oXG4gICAgICBvdXRwdXRDb3VudCxcbiAgICAgIHEsXG4gICAgICBrLFxuICAgICAgcGFzdEtleSxcbiAgICAgIGF0dGVudGlvbkJpYXMsXG4gICAgICBwYXJhbWV0ZXJzLFxuICAgICAgcGFzdFNlcXVlbmNlTGVuZ3RoLFxuICAgICAgc2VxTGVucyxcbiAgICAgIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCxcbiAgICApLFxuICAgIHsgaW5wdXRzOiBpbnB1dHNLLCBvdXRwdXRzOiBvdXRwdXRDb3VudCA+IDEgPyBbLTEsIDFdIDogWy0xXSB9LFxuICApWzBdO1xuXG4gIC8vIFJ1biBTb2Z0bWF4XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVJblBsYWNlU29mdG1heFByb2dyYW1JbmZvKFxuICAgICAgcHJvYnMsXG4gICAgICBwYXJhbWV0ZXJzLmJhdGNoU2l6ZSxcbiAgICAgIHBhcmFtZXRlcnMubnVtSGVhZHMsXG4gICAgICBwYXN0U2VxdWVuY2VMZW5ndGgsXG4gICAgICBwYXJhbWV0ZXJzLnNlcXVlbmNlTGVuZ3RoLFxuICAgICAgdG90YWxTZXF1ZW5jZUxlbmd0aCxcbiAgICAgIHNlcUxlbnMsXG4gICAgICB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQsXG4gICAgKSxcbiAgICB7IGlucHV0czogc2VxTGVucyAmJiB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQgPyBbcHJvYnMsIHNlcUxlbnMsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dF0gOiBbcHJvYnNdLCBvdXRwdXRzOiBbXSB9LFxuICApO1xuXG4gIC8vIFJ1biBBdHRlbnRpb25TY29yZVxuICBjb25zdCBpbnB1dHNWID0gW3Byb2JzLCB2XTtcbiAgaWYgKG91dHB1dENvdW50ID4gMSAmJiBwYXN0VmFsdWUgJiYgU2hhcGVVdGlsLnNpemUocGFzdFZhbHVlLmRpbXMpID4gMCkge1xuICAgIGlucHV0c1YucHVzaChwYXN0VmFsdWUpO1xuICB9XG4gIGlmIChzZXFMZW5zKSB7XG4gICAgaW5wdXRzVi5wdXNoKHNlcUxlbnMpO1xuICB9XG4gIGlmICh0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQpIHtcbiAgICBpbnB1dHNWLnB1c2godG90YWxTZXF1ZW5jZUxlbmd0aElucHV0KTtcbiAgfVxuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlVnhBdHRlbnRpb25TY29yZVByb2dyYW1JbmZvKFxuICAgICAgb3V0cHV0Q291bnQsXG4gICAgICBwcm9icyxcbiAgICAgIHYsXG4gICAgICBwYXN0VmFsdWUsXG4gICAgICBwYXJhbWV0ZXJzLFxuICAgICAgcGFzdFNlcXVlbmNlTGVuZ3RoLFxuICAgICAgc2VxTGVucyxcbiAgICAgIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCxcbiAgICApLFxuICAgIHtcbiAgICAgIGlucHV0czogaW5wdXRzVixcbiAgICAgIG91dHB1dHM6IG91dHB1dENvdW50ID4gMSA/IFswLCAyXSA6IFswXSxcbiAgICB9LFxuICApO1xufTtcblxuY29uc3QgcHJlcGFyZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgcGFyYW1ldGVyczogQXR0ZW50aW9uUGFyYW1ldGVycykgPT4ge1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IFtwYXJhbWV0ZXJzLmJhdGNoU2l6ZSwgcGFyYW1ldGVycy5udW1IZWFkcywgcGFyYW1ldGVycy5zZXF1ZW5jZUxlbmd0aCwgcGFyYW1ldGVycy5oZWFkU2l6ZV07XG4gIGNvbnN0IE0gPSBwYXJhbWV0ZXJzLnNlcXVlbmNlTGVuZ3RoO1xuICBjb25zdCBLID0gcGFyYW1ldGVycy5pbnB1dEhpZGRlblNpemU7XG4gIGNvbnN0IE4gPSBwYXJhbWV0ZXJzLmhlYWRTaXplO1xuICBjb25zdCBUSUxFX1NJWkUgPSAxMjtcbiAgY29uc3QgZGlzcGF0Y2ggPSB7XG4gICAgeDogTWF0aC5jZWlsKHBhcmFtZXRlcnMuaGVhZFNpemUgLyBUSUxFX1NJWkUpLFxuICAgIHk6IE1hdGguY2VpbChwYXJhbWV0ZXJzLnNlcXVlbmNlTGVuZ3RoIC8gVElMRV9TSVpFKSxcbiAgICB6OiBwYXJhbWV0ZXJzLmJhdGNoU2l6ZSAqIHBhcmFtZXRlcnMubnVtSGVhZHMsXG4gIH07XG4gIGNvbnN0IGlucHV0cyA9IFtjb250ZXh0LmlucHV0c1swXSwgY29udGV4dC5pbnB1dHNbMV0sIGNvbnRleHQuaW5wdXRzWzJdXTtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBNIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IEsgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogTiB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwYXJhbWV0ZXJzLm51bUhlYWRzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhcmFtZXRlcnMuaGVhZFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogcGFyYW1ldGVycy5oaWRkZW5TaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhcmFtZXRlcnMuaGlkZGVuU2l6ZSArIHBhcmFtZXRlcnMuaGlkZGVuU2l6ZSArIHBhcmFtZXRlcnMudkhpZGRlblNpemUgfSxcbiAgXTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBvdXRwdXRRID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dF9xJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZSk7XG4gICAgY29uc3Qgb3V0cHV0SyA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXRfaycsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUpO1xuICAgIGNvbnN0IG91dHB1dFYgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0X3YnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlKTtcbiAgICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ2lucHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcyk7XG4gICAgY29uc3Qgd2VpZ2h0ID0gaW5wdXRWYXJpYWJsZSgnd2VpZ2h0JywgaW5wdXRzWzFdLmRhdGFUeXBlLCBpbnB1dHNbMV0uZGltcyk7XG4gICAgY29uc3QgYmlhcyA9IGlucHV0VmFyaWFibGUoJ2JpYXMnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zKTtcbiAgICBjb25zdCBkYXRhVHlwZSA9IGlucHV0LnR5cGUuc3RvcmFnZTtcblxuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ00nLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnSycsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdOJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ251bV9oZWFkcycsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdoZWFkX3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnaGlkZGVuX3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnbGRiJywgdHlwZTogJ3UzMicgfSxcbiAgICBdO1xuICAgIHJldHVybiBgXG4gIGNvbnN0IFRJTEVfU0laRSA9ICR7VElMRV9TSVpFfXU7XG4gIHZhcjx3b3JrZ3JvdXA+IHRpbGVJbnB1dDogYXJyYXk8JHtkYXRhVHlwZX0sICR7VElMRV9TSVpFICogVElMRV9TSVpFfT47XG4gIHZhcjx3b3JrZ3JvdXA+IHRpbGVXZWlnaHRROiBhcnJheTwke2RhdGFUeXBlfSwgJHtUSUxFX1NJWkUgKiBUSUxFX1NJWkV9PjtcbiAgdmFyPHdvcmtncm91cD4gdGlsZVdlaWdodEs6IGFycmF5PCR7ZGF0YVR5cGV9LCAke1RJTEVfU0laRSAqIFRJTEVfU0laRX0+O1xuICB2YXI8d29ya2dyb3VwPiB0aWxlV2VpZ2h0VjogYXJyYXk8JHtkYXRhVHlwZX0sICR7VElMRV9TSVpFICogVElMRV9TSVpFfT47XG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIHdlaWdodCwgYmlhcywgb3V0cHV0USwgb3V0cHV0Sywgb3V0cHV0Vil9XG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydChbVElMRV9TSVpFLCBUSUxFX1NJWkUsIDFdKX1cbiAgICBsZXQgYmF0Y2hJbmRleCA9IHdvcmtncm91cF9pZC56IC8gdW5pZm9ybXMubnVtX2hlYWRzO1xuICAgIGxldCBoZWFkTnVtYmVyID0gd29ya2dyb3VwX2lkLnogJSB1bmlmb3Jtcy5udW1faGVhZHM7XG4gICAgbGV0IG0gPSBnbG9iYWxfaWQueTtcbiAgICBsZXQgbiA9IGdsb2JhbF9pZC54O1xuXG4gICAgbGV0IGlucHV0T2Zmc2V0ID0gYmF0Y2hJbmRleCAqICh1bmlmb3Jtcy5NICogdW5pZm9ybXMuSykgKyBtICogdW5pZm9ybXMuSztcbiAgICBsZXQgYmlhc09mZnNldFEgPSBoZWFkTnVtYmVyICogdW5pZm9ybXMuaGVhZF9zaXplO1xuICAgIGxldCBiaWFzT2Zmc2V0SyA9IHVuaWZvcm1zLmhpZGRlbl9zaXplICsgYmlhc09mZnNldFE7XG4gICAgbGV0IGJpYXNPZmZzZXRWID0gdW5pZm9ybXMuaGlkZGVuX3NpemUgKyBiaWFzT2Zmc2V0SztcblxuICAgIHZhciB2YWx1ZVEgPSAke2RhdGFUeXBlfSgwKTtcbiAgICB2YXIgdmFsdWVLID0gJHtkYXRhVHlwZX0oMCk7XG4gICAgdmFyIHZhbHVlViA9ICR7ZGF0YVR5cGV9KDApO1xuICAgIGZvciAodmFyIHc6IHUzMiA9IDB1OyB3IDwgdW5pZm9ybXMuSzsgdyArPSBUSUxFX1NJWkUpIHtcbiAgICAgIGlmIChtIDwgdW5pZm9ybXMuTSAmJiB3ICsgbG9jYWxfaWQueCA8IHVuaWZvcm1zLkspIHtcbiAgICAgICAgdGlsZUlucHV0W1RJTEVfU0laRSAqIGxvY2FsX2lkLnkgKyBsb2NhbF9pZC54XSA9IGlucHV0W2lucHV0T2Zmc2V0ICsgdyArIGxvY2FsX2lkLnhdO1xuICAgICAgfVxuICAgICAgaWYgKG4gPCB1bmlmb3Jtcy5OICYmIHcgKyBsb2NhbF9pZC55IDwgdW5pZm9ybXMuSykge1xuICAgICAgICBsZXQgb2Zmc2V0ID0gbiArICh3ICsgbG9jYWxfaWQueSkgKiB1bmlmb3Jtcy5sZGI7XG4gICAgICAgIHRpbGVXZWlnaHRRW1RJTEVfU0laRSAqIGxvY2FsX2lkLnkgKyBsb2NhbF9pZC54XSA9IHdlaWdodFtiaWFzT2Zmc2V0USArIG9mZnNldF07XG4gICAgICAgIHRpbGVXZWlnaHRLW1RJTEVfU0laRSAqIGxvY2FsX2lkLnkgKyBsb2NhbF9pZC54XSA9IHdlaWdodFtiaWFzT2Zmc2V0SyArIG9mZnNldF07XG4gICAgICAgIHRpbGVXZWlnaHRWW1RJTEVfU0laRSAqIGxvY2FsX2lkLnkgKyBsb2NhbF9pZC54XSA9IHdlaWdodFtiaWFzT2Zmc2V0ViArIG9mZnNldF07XG4gICAgICB9XG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgICBmb3IgKHZhciBrOiB1MzIgPSAwdTsgazxUSUxFX1NJWkUgJiYgdytrIDwgdW5pZm9ybXMuSzsgaysrKSB7XG4gICAgICAgIGxldCBpbnB1dFRpbGVPZmZzZXQgPSBUSUxFX1NJWkUgKiBsb2NhbF9pZC55ICsgaztcbiAgICAgICAgbGV0IHdlaWdodFRpbGVPZmZzZXQgPSBUSUxFX1NJWkUgKiBrICsgbG9jYWxfaWQueDtcbiAgICAgICAgdmFsdWVRICs9IHRpbGVJbnB1dFtpbnB1dFRpbGVPZmZzZXRdICogdGlsZVdlaWdodFFbd2VpZ2h0VGlsZU9mZnNldF07XG4gICAgICAgIHZhbHVlSyArPSB0aWxlSW5wdXRbaW5wdXRUaWxlT2Zmc2V0XSAqIHRpbGVXZWlnaHRLW3dlaWdodFRpbGVPZmZzZXRdO1xuICAgICAgICB2YWx1ZVYgKz0gdGlsZUlucHV0W2lucHV0VGlsZU9mZnNldF0gKiB0aWxlV2VpZ2h0Vlt3ZWlnaHRUaWxlT2Zmc2V0XTtcbiAgICAgIH1cblxuICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuICAgIH1cblxuICAgIGxldCBoZWFkT2Zmc2V0ID0gKG0gKiB1bmlmb3Jtcy5OICsgbikgJSB1bmlmb3Jtcy5oZWFkX3NpemU7XG4gICAgdmFsdWVRICs9IGJpYXNbaGVhZE9mZnNldCArIGJpYXNPZmZzZXRRXTtcbiAgICB2YWx1ZUsgKz0gYmlhc1toZWFkT2Zmc2V0ICsgYmlhc09mZnNldEtdO1xuICAgIHZhbHVlViArPSBiaWFzW2hlYWRPZmZzZXQgKyBiaWFzT2Zmc2V0Vl07XG5cbiAgICBsZXQgb2Zmc2V0ID0gd29ya2dyb3VwX2lkLnogKiB1bmlmb3Jtcy5NICogdW5pZm9ybXMuTjtcbiAgICBpZiAobSA8IHVuaWZvcm1zLk0gJiYgbiA8IHVuaWZvcm1zLk4pIHtcbiAgICAgIGxldCBvdXRwdXRJZHggPSBvZmZzZXQgKyBtICogdW5pZm9ybXMuTiArIG47XG4gICAgICBvdXRwdXRfcVtvdXRwdXRJZHhdID0gdmFsdWVRO1xuICAgICAgb3V0cHV0X2tbb3V0cHV0SWR4XSA9IHZhbHVlSztcbiAgICAgIG91dHB1dF92W291dHB1dElkeF0gPSB2YWx1ZVY7XG4gICAgfVxuICB9YDtcbiAgfTtcblxuICByZXR1cm4gY29udGV4dC5jb21wdXRlKFxuICAgIHtcbiAgICAgIG5hbWU6ICdBdHRlbnRpb25QcmVwYXJlJyxcbiAgICAgIHNoYWRlckNhY2hlOiB7IGlucHV0RGVwZW5kZW5jaWVzOiBbJ3R5cGUnLCAndHlwZScsICd0eXBlJ10gfSxcbiAgICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICB7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUsIGdwdURhdGFUeXBlOiBHcHVEYXRhVHlwZS5kZWZhdWx0IH0sXG4gICAgICAgICAgeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCB9LFxuICAgICAgICAgIHsgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSwgZ3B1RGF0YVR5cGU6IEdwdURhdGFUeXBlLmRlZmF1bHQgfSxcbiAgICAgICAgXSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogZGlzcGF0Y2gsXG4gICAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICAgIH0pLFxuICAgICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIH0sXG4gICAgeyBpbnB1dHMsIG91dHB1dHM6IFstMSwgLTEsIC0xXSB9LFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGF0dGVudGlvbiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQXR0ZW50aW9uQXR0cnMpOiB2b2lkID0+IHtcbiAgY29uc3QgcGFyYW1zID0gdmFsaWRhdGVBdHRlbnRpb25JbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuXG4gIGNvbnN0IFtxLCBrLCB2XSA9IHByZXBhcmUoY29udGV4dCwgcGFyYW1zKTtcblxuICByZXR1cm4gYXBwbHlBdHRlbnRpb24oXG4gICAgY29udGV4dCxcbiAgICBxLFxuICAgIGssXG4gICAgdixcbiAgICBjb250ZXh0LmlucHV0c1s0XSxcbiAgICB1bmRlZmluZWQsXG4gICAgdW5kZWZpbmVkLFxuICAgIHVuZGVmaW5lZCxcbiAgICBjb250ZXh0LmlucHV0c1s1XSxcbiAgICBwYXJhbXMsXG4gICk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBlbnYgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbyB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsIGdldE1heENvbXBvbmVudHMsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQmF0Y2hOb3JtQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGVwc2lsb246IG51bWJlcjtcbiAgcmVhZG9ubHkgbW9tZW50dW06IG51bWJlcjtcbiAgcmVhZG9ubHkgc3BhdGlhbDogYm9vbGVhbjtcbiAgcmVhZG9ubHkgdHJhaW5pbmdNb2RlOiBib29sZWFuO1xuICByZWFkb25seSBmb3JtYXQ6ICdOSFdDJyB8ICdOQ0hXJztcbiAgcmVhZG9ubHkgb3V0cHV0Q291bnQ6IG51bWJlcjtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IEJhdGNoTm9ybUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gNSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQmF0Y2hOb3JtYWxpemF0aW9uIHJlcXVpcmVzIDUgaW5wdXRzJyk7XG4gIH1cblxuICBjb25zdCBjaGVja1NoYXBlRXF1YWwgPSAoYWN0dWFsOiByZWFkb25seSBudW1iZXJbXSwgZXhwZWN0ZWQ6IHJlYWRvbmx5IG51bWJlcltdLCBtZXNzYWdlOiBzdHJpbmcpID0+IHtcbiAgICBjb25zdCByID0gZXhwZWN0ZWQubGVuZ3RoO1xuICAgIGlmIChyICE9PSBhY3R1YWwubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bWVzc2FnZX06IG51bSBkaW1lbnNpb25zICE9ICR7cn1gKTtcbiAgICB9XG4gICAgZXhwZWN0ZWQuZm9yRWFjaCgodiwgaSkgPT4ge1xuICAgICAgaWYgKHYgIT09IGFjdHVhbFtpXSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bWVzc2FnZX06IGRpbVske2l9XSBkbyBub3QgbWF0Y2hgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcblxuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoID4gMSkge1xuICAgIGNvbnN0IHNoYXBlID1cbiAgICAgIGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQydcbiAgICAgICAgPyBhdHRyaWJ1dGVzLnNwYXRpYWxcbiAgICAgICAgICA/IGlucHV0c1swXS5kaW1zLnNsaWNlKC0xKVxuICAgICAgICAgIDogaW5wdXRzWzBdLmRpbXMuc2xpY2UoLTEpLmNvbmNhdChpbnB1dHNbMF0uZGltcy5zbGljZSgxLCBpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAxKSlcbiAgICAgICAgOiBpbnB1dHNbMF0uZGltcy5zbGljZSgxLCBhdHRyaWJ1dGVzLnNwYXRpYWwgPyAyIDogdW5kZWZpbmVkKTtcbiAgICBjaGVja1NoYXBlRXF1YWwoaW5wdXRzWzFdLmRpbXMsIHNoYXBlLCAnSW52YWxpZCBpbnB1dCBzY2FsZScpO1xuICAgIGNoZWNrU2hhcGVFcXVhbChpbnB1dHNbMl0uZGltcywgc2hhcGUsICdJbnZhbGlkIGlucHV0IEInKTtcbiAgICBjaGVja1NoYXBlRXF1YWwoaW5wdXRzWzNdLmRpbXMsIHNoYXBlLCAnSW52YWxpZCBpbnB1dCBtZWFuJyk7XG4gICAgY2hlY2tTaGFwZUVxdWFsKGlucHV0c1s0XS5kaW1zLCBzaGFwZSwgJ0ludmFsaWQgaW5wdXQgdmFyJyk7XG4gIH0gZWxzZSB7XG4gICAgY2hlY2tTaGFwZUVxdWFsKGlucHV0c1sxXS5kaW1zLCBbMV0sICdJbnZhbGlkIGlucHV0IHNjYWxlJyk7XG4gICAgY2hlY2tTaGFwZUVxdWFsKGlucHV0c1syXS5kaW1zLCBbMV0sICdJbnZhbGlkIGlucHV0IEInKTtcbiAgICBjaGVja1NoYXBlRXF1YWwoaW5wdXRzWzNdLmRpbXMsIFsxXSwgJ0ludmFsaWQgaW5wdXQgbWVhbicpO1xuICAgIGNoZWNrU2hhcGVFcXVhbChpbnB1dHNbNF0uZGltcywgWzFdLCAnSW52YWxpZCBpbnB1dCB2YXInKTtcbiAgfVxufTtcblxuY29uc3QgY3JlYXRlQmF0Y2hOb3JtSW5mZXJlbmNlUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBCYXRjaE5vcm1BdHRyaWJ1dGVzLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCB7IGVwc2lsb24sIHNwYXRpYWwsIGZvcm1hdCB9ID0gYXR0cmlidXRlcztcbiAgY29uc3QgeVNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBzcGF0aWFsID8gZ2V0TWF4Q29tcG9uZW50cyh5U2hhcGVbeVNoYXBlLmxlbmd0aCAtIDFdKSA6IDE7XG4gIGNvbnN0IGNDb21wb25lbnRzID0gZm9ybWF0ID09PSAnTkhXQycgJiYgeVNoYXBlLmxlbmd0aCA+IDEgPyBjb21wb25lbnRzIDogMTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKHlTaGFwZSkgLyBjb21wb25lbnRzO1xuICAvLyBPbmx5IHN1cHBvcnQgdW5pZm9ybXMgZm9yIG9wc2V0IHZlcnNpb24gPj0gOSAoc3BhdGlhbCA9IHRydWUpLlxuICBjb25zdCB1c2VTaGFwZXNVbmlmb3JtcyA9IHNwYXRpYWw7XG4gIGNvbnN0IHNoYXBlT3JSYW5rID0gdXNlU2hhcGVzVW5pZm9ybXMgPyB5U2hhcGUubGVuZ3RoIDogeVNoYXBlO1xuICBjb25zdCB4ID0gaW5wdXRWYXJpYWJsZSgneCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMsIGNvbXBvbmVudHMpO1xuICBjb25zdCBzY2FsZSA9IGlucHV0VmFyaWFibGUoJ3NjYWxlJywgaW5wdXRzWzFdLmRhdGFUeXBlLCBpbnB1dHNbMV0uZGltcywgY0NvbXBvbmVudHMpO1xuICBjb25zdCBiaWFzID0gaW5wdXRWYXJpYWJsZSgnYmlhcycsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMsIGNDb21wb25lbnRzKTtcbiAgY29uc3QgaW5wdXRNZWFuID0gaW5wdXRWYXJpYWJsZSgnaW5wdXRNZWFuJywgaW5wdXRzWzNdLmRhdGFUeXBlLCBpbnB1dHNbM10uZGltcywgY0NvbXBvbmVudHMpO1xuICBjb25zdCBpbnB1dFZhciA9IGlucHV0VmFyaWFibGUoJ2lucHV0VmFyJywgaW5wdXRzWzRdLmRhdGFUeXBlLCBpbnB1dHNbNF0uZGltcywgY0NvbXBvbmVudHMpO1xuICBjb25zdCB5ID0gb3V0cHV0VmFyaWFibGUoJ3knLCBpbnB1dHNbMF0uZGF0YVR5cGUsIHNoYXBlT3JSYW5rLCBjb21wb25lbnRzKTtcbiAgLy8gVE9ETzogc3VwcG9ydCBpbnB1dHMgd2l0aCBkaWZmZXJlbnQgZGF0YSB0eXBlLiBDdXJyZW50IHdlIG5lZWQgdG8gbWFrZSBzdXJlIGFsbCBpbnB1dHMgaGF2ZSB0aGUgc2FtZSBkYXRhIHR5cGUuXG4gIC8vIE90aGVyd2lzZSwgdGhlIHNoYWRlciBjb21waWxhdGlvbiB3aWxsIGZhaWwuXG4gIGNvbnN0IGNhbGNDT2Zmc2V0ID0gKCk6IHN0cmluZyA9PiB7XG4gICAgbGV0IGNPZmZzZXQgPSAnJztcbiAgICBpZiAoc3BhdGlhbCkge1xuICAgICAgY09mZnNldCA9IGBsZXQgY09mZnNldCA9ICR7XG4gICAgICAgIHlTaGFwZS5sZW5ndGggPT09IDFcbiAgICAgICAgICA/ICcwdSdcbiAgICAgICAgICA6IGZvcm1hdCA9PT0gJ05IV0MnXG4gICAgICAgICAgICA/IGBvdXRwdXRJbmRpY2VzWyR7eVNoYXBlLmxlbmd0aCAtIDF9XSAvICR7Y29tcG9uZW50c31gXG4gICAgICAgICAgICA6ICdvdXRwdXRJbmRpY2VzWzFdJ1xuICAgICAgfTtgO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoZm9ybWF0ID09PSAnTkNIVycpIHtcbiAgICAgICAgY09mZnNldCA9IGBcbiAgICAgICAgICAgICR7eS5pbmRpY2VzU2V0KCdvdXRwdXRJbmRpY2VzJywgJzAnLCAnMCcpfVxuICAgICAgICAgICAgbGV0IGNPZmZzZXQgPSAke3kuaW5kaWNlc1RvT2Zmc2V0KCdvdXRwdXRJbmRpY2VzJyl9O2A7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyB1cGRhdGUgQyBjaGFubmVsLlxuICAgICAgICBjT2Zmc2V0ID0gYHZhciBjSW5kaWNlcyA9ICR7c2NhbGUudHlwZS5pbmRpY2VzfSgwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgY0luZGljZXNbMF0gPSBvdXRwdXRJbmRpY2VzWyR7eVNoYXBlLmxlbmd0aCAtIDF9XTtgO1xuICAgICAgICAvLyB1cGRhdGUgRDEgeCAuLi4geCBEbiBjaGFubmVscy5cbiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBzY2FsZS5yYW5rOyBpKyspIHtcbiAgICAgICAgICBjT2Zmc2V0ICs9IGBjSW5kaWNlc1ske2l9XSA9IG91dHB1dEluZGljZXNbJHtpfV07YDtcbiAgICAgICAgfVxuICAgICAgICBjT2Zmc2V0ICs9IGBsZXQgY09mZnNldCA9ICR7c2NhbGUuaW5kaWNlc1RvT2Zmc2V0KCdjSW5kaWNlcycpfTtgO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY09mZnNldDtcbiAgfTtcbiAgY29uc3QgZ2V0SW5mZXJlbmNlTW9kZVNoYWRlclNvdXJjZSA9IChoZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICBjb25zdCBlcHNpbG9uID0gJHtlcHNpbG9ufTtcbiAgJHtoZWxwZXIucmVnaXN0ZXJVbmlmb3JtKCdvdXRwdXRTaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMoeCwgc2NhbGUsIGJpYXMsIGlucHV0TWVhbiwgaW5wdXRWYXIsIHkpfVxuICAke2hlbHBlci5tYWluU3RhcnQoKX1cbiAgJHtoZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0U2l6ZScpfVxuICAgIHZhciBvdXRwdXRJbmRpY2VzID0gJHt5Lm9mZnNldFRvSW5kaWNlcyhgZ2xvYmFsX2lkeCAqICR7Y29tcG9uZW50c31gKX07XG4gICAgJHtjYWxjQ09mZnNldCgpfVxuICAgIGxldCBzY2FsZSA9ICR7c2NhbGUuZ2V0QnlPZmZzZXQoJ2NPZmZzZXQnKX07XG4gICAgbGV0IGJpYXMgPSAke2JpYXMuZ2V0QnlPZmZzZXQoJ2NPZmZzZXQnKX07XG4gICAgbGV0IGlucHV0TWVhbiA9ICR7aW5wdXRNZWFuLmdldEJ5T2Zmc2V0KCdjT2Zmc2V0Jyl9O1xuICAgIGxldCBpbnB1dFZhciA9ICR7aW5wdXRWYXIuZ2V0QnlPZmZzZXQoJ2NPZmZzZXQnKX07XG4gICAgbGV0IHggPSAke3guZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKX07XG4gICAgbGV0IHZhbHVlID0gKHggLSBpbnB1dE1lYW4pICogaW52ZXJzZVNxcnQoaW5wdXRWYXIgKyBlcHNpbG9uKSAqIHNjYWxlICsgYmlhcztcbiAgICAke3kuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAndmFsdWUnKX1cbiAgfWA7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0JhdGNoTm9ybWFsaXphdGlvbicsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2F0dHJpYnV0ZXMuZXBzaWxvbn1fJHthdHRyaWJ1dGVzLmZvcm1hdH1fJHtzcGF0aWFsfV8ke2NvbXBvbmVudHN9YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzOiB1c2VTaGFwZXNVbmlmb3JtcyA/IFsncmFuaycsICd0eXBlJywgJ3R5cGUnLCAndHlwZScsICd0eXBlJ10gOiB1bmRlZmluZWQsXG4gICAgfSxcbiAgICBnZXRTaGFkZXJTb3VyY2U6IGdldEluZmVyZW5jZU1vZGVTaGFkZXJTb3VyY2UsXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IGlucHV0c1swXS5kaW1zLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zOiB1c2VTaGFwZXNVbmlmb3Jtc1xuICAgICAgICA/IFt7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LCAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyh5U2hhcGUpXVxuICAgICAgICA6IFt7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9XSxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUJhdGNoTm9ybUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBCYXRjaE5vcm1BdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleShhdHRyaWJ1dGVzIGFzIE9taXQ8QmF0Y2hOb3JtQXR0cmlidXRlcywga2V5b2YgQXR0cmlidXRlV2l0aENhY2hlS2V5Pik7XG5cbmV4cG9ydCBjb25zdCBiYXRjaE5vcm0gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogdm9pZCA9PiB7XG4gIGNvbnN0IHsgaW5wdXRzLCBvdXRwdXRDb3VudCB9ID0gY29udGV4dDtcbiAgY29uc3QgdXBkYXRlZEF0dHJpYnV0ZXMgPSBwYXJzZUJhdGNoTm9ybUF0dHJpYnV0ZXMoeyAuLi5hdHRyaWJ1dGVzLCBvdXRwdXRDb3VudCB9KTtcbiAgaWYgKGVudi53ZWJncHUudmFsaWRhdGVJbnB1dENvbnRlbnQpIHtcbiAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMsIHVwZGF0ZWRBdHRyaWJ1dGVzKTtcbiAgfVxuICBpZiAoYXR0cmlidXRlcy50cmFpbmluZ01vZGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0JhdGNoTm9ybWFsaXphdGlvbiB0cmFpbmluZ01vZGUgaXMgbm90IHN1cHBvcnRlZCB5ZXQuJyk7XG4gIH0gZWxzZSB7XG4gICAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUJhdGNoTm9ybUluZmVyZW5jZVByb2dyYW1JbmZvKGlucHV0cywgdXBkYXRlZEF0dHJpYnV0ZXMpKTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoICE9PSAzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCBzaG91bGQgaGF2ZSAzIGRpbWVuc2lvbnMnKTtcbiAgfVxuXG4gIGlmICghWzMyMCwgNjQwLCAxMjgwXS5pbmNsdWRlcyhpbnB1dHNbMF0uZGltc1syXSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ251bWJlciBvZiBjaGFubmVscyBzaG91bGQgYmUgMzIwLCA2NDAgb3IgMTI4MCcpO1xuICB9XG5cbiAgaWYgKGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignYmlhcyBpcyBleHBlY3RlZCB0byBoYXZlIDEgZGltZW5zaW9ucycpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS5kaW1zWzJdICE9PSBpbnB1dHNbMV0uZGltc1swXSkge1xuICAgIHRocm93IG5ldyBFcnJvcignbGFzdCBkaW1lbnNpb24gb2YgaW5wdXQgYW5kIGJpYXMgYXJlIG5vdCB0aGUgc2FtZScpO1xuICB9XG59O1xuXG5jb25zdCBjcmVhdGVCaWFzQWRkUHJvZ3JhbUluZm8gPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG5cbiAgY29uc3QgY2hhbm5lbHMgPSBpbnB1dHNbMF0uZGltc1syXTtcbiAgLy8gc2luY2UgY2hhbm5lbCBudW1iZXIgY2FuIGJlIG9ubHkgMzIwLzY0MC8xMjgwLCBpdCdzIGFsd2F5cyBkaXZpc2FibGUgYnkgNFxuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gNDtcblxuICBjb25zdCBkYXRhVHlwZSA9IGlucHV0c1swXS5kYXRhVHlwZTtcbiAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGRhdGFUeXBlLCBvdXRwdXRTaGFwZSwgNCk7XG4gIGNvbnN0IGJpYXMgPSBpbnB1dFZhcmlhYmxlKCdiaWFzJywgZGF0YVR5cGUsIFtjaGFubmVsc10sIDQpO1xuICBjb25zdCByZXNpZHVhbCA9IGlucHV0VmFyaWFibGUoJ3Jlc2lkdWFsJywgZGF0YVR5cGUsIG91dHB1dFNoYXBlLCA0KTtcbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGRhdGFUeXBlLCBvdXRwdXRTaGFwZSwgNCk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gIGNvbnN0IGNoYW5uZWxzID0gJHtjaGFubmVsc311IC8gNDtcbiAgJHtzaGFkZXJIZWxwZXIuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgYmlhcywgcmVzaWR1YWwsIG91dHB1dCl9XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcyhvdXRwdXRTaXplKX1cbiAgICBsZXQgdmFsdWUgPSAke2lucHV0LmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4Jyl9XG4gICAgICArICR7Ymlhcy5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCAlIGNoYW5uZWxzJyl9ICsgJHtyZXNpZHVhbC5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpfTtcbiAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICd2YWx1ZScpfVxuICB9YDtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdCaWFzQWRkJyxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGJpYXNBZGQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlQmlhc0FkZFByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzKSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUsXG4gIFVuaWZvcm1EYXRhRWxlbWVudFR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbnR5cGUgQnVpbHRpbkZ1bmN0aW9uTmFtZSA9IHN0cmluZztcbnR5cGUgRWxlbWVudHdpc2VDdXN0b21FeHByZXNzaW9uID0gKGV4cHJlc3Npb246IHN0cmluZykgPT4gc3RyaW5nO1xudHlwZSBFbGVtZW50d2lzZUZ1bmN0aW9uQ2FsbCA9IEJ1aWx0aW5GdW5jdGlvbk5hbWUgfCBFbGVtZW50d2lzZUN1c3RvbUV4cHJlc3Npb247XG5cbmNvbnN0IGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbVNoYWRlciA9IChcbiAgc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIsXG4gIGRhdGFzaXplOiBudW1iZXIsXG4gIGlucHV0RGF0YVR5cGU6IG51bWJlcixcbiAgb3V0cHV0RGF0YVR5cGU6IG51bWJlcixcbiAgZnVuY0NhbGw6IEVsZW1lbnR3aXNlRnVuY3Rpb25DYWxsLFxuICBhZGRpdGlvbmFsSW1wbGVtZW50YXRpb24/OiBzdHJpbmcsXG4gIGFkZGl0aW9uYWxVbmlmb3Jtc1R5cGU/OiBVbmlmb3Jtc0FycmF5VHlwZSxcbik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IHZlY1NpemUgPSBNYXRoLmNlaWwoZGF0YXNpemUgLyA0KTtcblxuICBsZXQgZXhwcmVzc2lvbiA9ICcnO1xuICBpZiAodHlwZW9mIGZ1bmNDYWxsID09PSAnc3RyaW5nJykge1xuICAgIGV4cHJlc3Npb24gPSBgJHtmdW5jQ2FsbH0oYSlgO1xuICB9IGVsc2Uge1xuICAgIGV4cHJlc3Npb24gPSBmdW5jQ2FsbCgnYScpO1xuICB9XG5cbiAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dERhdGEnLCBpbnB1dERhdGFUeXBlLCBbdmVjU2l6ZV0sIDQpO1xuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0RGF0YScsIG91dHB1dERhdGFUeXBlLCBbdmVjU2l6ZV0sIDQpO1xuICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbeyBuYW1lOiAndmVjX3NpemUnLCB0eXBlOiAndTMyJyB9XTtcbiAgaWYgKGFkZGl0aW9uYWxVbmlmb3Jtc1R5cGUpIHtcbiAgICB1bmlmb3Jtcy5wdXNoKC4uLmFkZGl0aW9uYWxVbmlmb3Jtc1R5cGUpO1xuICB9XG5cbiAgcmV0dXJuIGBcbiAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIG91dHB1dCl9XG5cbiAgJHthZGRpdGlvbmFsSW1wbGVtZW50YXRpb24gPz8gJyd9XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMudmVjX3NpemUnKX1cblxuICAgIGxldCBhID0gJHtpbnB1dC5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpfTtcbiAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsIGV4cHJlc3Npb24pfVxuICB9YDtcbn07XG5cbmNvbnN0IGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0OiBUZW5zb3JWaWV3LFxuICBuYW1lOiBzdHJpbmcsXG4gIGZ1bmNDYWxsOiBFbGVtZW50d2lzZUZ1bmN0aW9uQ2FsbCxcbiAgYWRkaXRpb25hbEltcGxlbWVudGF0aW9uPzogc3RyaW5nLFxuICBjYWNoZUtleT86IHN0cmluZyxcbiAgb3V0cHV0RGF0YVR5cGU6IG51bWJlciA9IGlucHV0LmRhdGFUeXBlLFxuICBhZGRpdGlvbmFsVW5pZm9ybXM/OiBQcm9ncmFtVW5pZm9ybVtdLFxuICBhZGRpdGlvbmFsVW5pZm9ybXNUeXBlPzogVW5pZm9ybXNBcnJheVR5cGUsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplKGlucHV0LmRpbXMpIC8gNCkgfSxcbiAgXTtcbiAgaWYgKGFkZGl0aW9uYWxVbmlmb3Jtcykge1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmFkZGl0aW9uYWxVbmlmb3Jtcyk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG5hbWUsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogY2FjaGVLZXksIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3R5cGUnXSB9LFxuICAgIGdldFNoYWRlclNvdXJjZTogKHNoYWRlckhlbHBlcikgPT5cbiAgICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbVNoYWRlcihcbiAgICAgICAgc2hhZGVySGVscGVyLFxuICAgICAgICBTaGFwZVV0aWwuc2l6ZShpbnB1dC5kaW1zKSxcbiAgICAgICAgaW5wdXQuZGF0YVR5cGUsXG4gICAgICAgIG91dHB1dERhdGFUeXBlLFxuICAgICAgICBmdW5jQ2FsbCxcbiAgICAgICAgYWRkaXRpb25hbEltcGxlbWVudGF0aW9uLFxuICAgICAgICBhZGRpdGlvbmFsVW5pZm9ybXNUeXBlLFxuICAgICAgKSxcbiAgICBnZXRSdW5EYXRhOiAoaW5wdXRUZW5zb3JzKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogaW5wdXQuZGltcywgZGF0YVR5cGU6IG91dHB1dERhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDoge1xuICAgICAgICB4OiBNYXRoLmNlaWwoU2hhcGVVdGlsLnNpemUoaW5wdXRUZW5zb3JzWzBdLmRpbXMpIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8gLyA0IC8qIHZlYyBzaXplICovKSxcbiAgICAgIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgYWJzID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnQWJzJywgJ2FicycpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBhY29zID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnQWNvcycsICdhY29zJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IGFjb3NoID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnQWNvc2gnLCAnYWNvc2gnKSk7XG59O1xuXG5leHBvcnQgY29uc3QgYXNpbiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0FzaW4nLCAnYXNpbicpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBhc2luaCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0FzaW5oJywgJ2FzaW5oJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IGF0YW4gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdBdGFuJywgJ2F0YW4nKSk7XG59O1xuZXhwb3J0IGNvbnN0IGF0YW5oID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnQXRhbmgnLCAnYXRhbmgnKSk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIENhc3RBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgdG86IG51bWJlcjtcbiAgcmVhZG9ubHkgc2F0dXJhdGU/OiBib29sZWFuO1xufVxuXG5leHBvcnQgY29uc3QgcGFyc2VDYXN0QXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IENhc3RBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleShhdHRyaWJ1dGVzIGFzIHsgdG86IG51bWJlciB9KTtcblxuZXhwb3J0IGNvbnN0IGNhc3QgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IENhc3RBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGxldCBmdW5jOiBFbGVtZW50d2lzZUZ1bmN0aW9uQ2FsbDtcbiAgc3dpdGNoIChhdHRyaWJ1dGVzLnRvKSB7XG4gICAgY2FzZSBEYXRhVHlwZS5mbG9hdDE2OlxuICAgICAgZnVuYyA9ICd2ZWM0PGYxNj4nO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBEYXRhVHlwZS5mbG9hdDpcbiAgICAgIGZ1bmMgPSAndmVjNDxmMzI+JztcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgRGF0YVR5cGUudWludDMyOlxuICAgICAgZnVuYyA9ICd2ZWM0PHUzMj4nO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQzMjpcbiAgICAgIGZ1bmMgPSAndmVjNDxpMzI+JztcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgRGF0YVR5cGUuYm9vbDpcbiAgICAgIGZ1bmMgPSAndmVjNDxib29sPic7XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoYG5vdCBzdXBwb3J0ZWQgdHlwZSAoc3BlY2lmaWVkIGluIGF0dHJpYnV0ZSAndG8nIGZyb20gJ0Nhc3QnIG9wZXJhdG9yKTogJHthdHRyaWJ1dGVzLnRvfWApO1xuICB9XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnQ2FzdCcsIGZ1bmMsIHVuZGVmaW5lZCwgYXR0cmlidXRlcy5jYWNoZUtleSwgYXR0cmlidXRlcy50byksXG4gICk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIENsaXBBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgbWluOiBudW1iZXI7XG4gIHJlYWRvbmx5IG1heDogbnVtYmVyO1xufVxuXG5jb25zdCBnZW5lcmF0ZUNsaXBBdHRyaWJ1dGVzRnJvbUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IENsaXBBdHRyaWJ1dGVzID0+IHtcbiAgbGV0IG1pbjogbnVtYmVyO1xuICBsZXQgbWF4OiBudW1iZXI7XG4gIGNvbnN0IGhhc01pbiA9IGlucHV0cy5sZW5ndGggPj0gMiAmJiBpbnB1dHNbMV0uZGF0YSAhPT0gMDtcbiAgY29uc3QgaGFzTWF4ID0gaW5wdXRzLmxlbmd0aCA+PSAzICYmIGlucHV0c1syXS5kYXRhICE9PSAwO1xuXG4gIHN3aXRjaCAoaW5wdXRzWzBdLmRhdGFUeXBlKSB7XG4gICAgY2FzZSBEYXRhVHlwZS5mbG9hdDpcbiAgICAgIG1pbiA9IGhhc01pbiA/IGlucHV0c1sxXS5nZXRGbG9hdDMyQXJyYXkoKVswXSA6IC0zLjQwMjgyMzQ2NjM4NTI4ODZlMzg7XG4gICAgICBtYXggPSBoYXNNYXggPyBpbnB1dHNbMl0uZ2V0RmxvYXQzMkFycmF5KClbMF0gOiAzLjQwMjgyMzQ2NjM4NTI4ODZlMzg7XG4gICAgICBicmVhaztcbiAgICBjYXNlIERhdGFUeXBlLmZsb2F0MTY6XG4gICAgICBtaW4gPSBoYXNNaW4gPyBpbnB1dHNbMV0uZ2V0VWludDE2QXJyYXkoKVswXSA6IDY0NTExOyAvLyB1aW50MTYoNjQ1MTEpIDwtPiBmbG9hdDE2KC02NTUwNC4wKVxuICAgICAgbWF4ID0gaGFzTWF4ID8gaW5wdXRzWzJdLmdldFVpbnQxNkFycmF5KClbMF0gOiAzMTc0MzsgLy8gdWludDE2KDMxNzQzKSA8LT4gZmxvYXQxNig2NTUwNC4wKVxuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5zdXBwb3J0IGRhdGEgdHlwZScpO1xuICB9XG5cbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IG1pbiwgbWF4IH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGNsaXAgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGNsaXBBdHRyaWJ1dGVzOiBDbGlwQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBhdHRyaWJ1dGVzID0gY2xpcEF0dHJpYnV0ZXMgPyBjbGlwQXR0cmlidXRlcyA6IGdlbmVyYXRlQ2xpcEF0dHJpYnV0ZXNGcm9tSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlKGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oXG4gICAgICBjb250ZXh0LmlucHV0c1swXSxcbiAgICAgICdDbGlwJyxcbiAgICAgIChhKSA9PiBgY2xhbXAoJHthfSwgdmVjNDwke2RhdGFUeXBlfT4odW5pZm9ybXMubWluKSwgdmVjNDwke2RhdGFUeXBlfT4odW5pZm9ybXMubWF4KSlgLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgYXR0cmlidXRlcy5jYWNoZUtleSxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIFtcbiAgICAgICAgeyB0eXBlOiBjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSwgZGF0YTogYXR0cmlidXRlcy5taW4gfSxcbiAgICAgICAgeyB0eXBlOiBjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSwgZGF0YTogYXR0cmlidXRlcy5tYXggfSxcbiAgICAgIF0sXG4gICAgICBbXG4gICAgICAgIHsgbmFtZTogJ21pbicsIHR5cGU6IGRhdGFUeXBlIGFzIFVuaWZvcm1EYXRhRWxlbWVudFR5cGUgfSxcbiAgICAgICAgeyBuYW1lOiAnbWF4JywgdHlwZTogZGF0YVR5cGUgYXMgVW5pZm9ybURhdGFFbGVtZW50VHlwZSB9LFxuICAgICAgXSxcbiAgICApLFxuICAgIHsgaW5wdXRzOiBbMF0gfSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBjZWlsID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnQ2VpbCcsICdjZWlsJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IGNvcyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0NvcycsICdjb3MnKSk7XG59O1xuXG5leHBvcnQgY29uc3QgY29zaCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0Nvc2gnLCAnY29zaCcpKTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWxwaGFBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYWxwaGE6IG51bWJlcjtcbn1cblxuZXhwb3J0IGNvbnN0IHBhcnNlQWxwaGFBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogQWxwaGFBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleShhdHRyaWJ1dGVzIGFzIHsgYWxwaGE6IG51bWJlciB9KTtcblxuZXhwb3J0IGNvbnN0IGVsdSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQWxwaGFBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSk7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0sXG4gICAgICAnRWx1JyxcbiAgICAgIChhKSA9PiBgZWx1X3ZmMzIoJHthfSlgLFxuICAgICAgYFxuICBjb25zdCBlbHVfYWxwaGFfID0gJHtkYXRhVHlwZX0oJHthdHRyaWJ1dGVzLmFscGhhfSk7XG5cbiAgZm4gZWx1X2YzMihhOiAke2RhdGFUeXBlfSkgLT4gJHtkYXRhVHlwZX0ge1xuICByZXR1cm4gc2VsZWN0KChleHAoYSkgLSAxLjApICogZWx1X2FscGhhXywgYSwgYSA+PSAwLjApO1xuICB9XG5cbiAgZm4gZWx1X3ZmMzIodjogdmVjNDwke2RhdGFUeXBlfT4pIC0+IHZlYzQ8JHtkYXRhVHlwZX0+IHtcbiAgcmV0dXJuIHZlYzQoZWx1X2YzMih2LngpLCBlbHVfZjMyKHYueSksIGVsdV9mMzIodi56KSwgZWx1X2YzMih2LncpKTtcbiAgfWAsXG4gICAgICBhdHRyaWJ1dGVzLmNhY2hlS2V5LFxuICAgICksXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgZXJmSW1wbCA9ICh2YXJUeXBlID0gJ2YzMicpID0+IGBcbmNvbnN0IHIwOiAke3ZhclR5cGV9ID0gMC4zMjc1OTExO1xuY29uc3QgcjE6ICR7dmFyVHlwZX0gPSAwLjI1NDgyOTU5MjtcbmNvbnN0IHIyOiAke3ZhclR5cGV9ID0gLTAuMjg0NDk2NzM2O1xuY29uc3QgcjM6ICR7dmFyVHlwZX0gPSAxLjQyMTQxMzc0MTtcbmNvbnN0IHI0OiAke3ZhclR5cGV9ID0gLTEuNDUzMTUyMDI3O1xuY29uc3QgcjU6ICR7dmFyVHlwZX0gPSAxLjA2MTQwNTQyOTtcblxuZm4gZXJmX3ZmMzIodjogdmVjNDwke3ZhclR5cGV9PikgLT4gdmVjNDwke3ZhclR5cGV9PiB7XG4gIGxldCBhYnN2ID0gYWJzKHYpO1xuICBsZXQgeCA9IDEuMCAvICgxLjAgKyByMCAqIGFic3YpO1xuICByZXR1cm4gc2lnbih2KSAqICgxLjAgLSAoKCgocjUgKiB4ICsgcjQpICogeCArIHIzKSAqIHggKyByMikgKiB4ICsgcjEpICogeCAqIGV4cCgtYWJzdiAqIGFic3YpKTtcbn1gO1xuXG5leHBvcnQgY29uc3QgZXJmID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnRXJmJywgKGEpID0+IGBlcmZfdmYzMigke2F9KWAsIGVyZkltcGwoZGF0YVR5cGUpKSk7XG59O1xuXG5leHBvcnQgY29uc3QgZXhwID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnRXhwJywgJ2V4cCcpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBmbG9vciA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ0Zsb29yJywgJ2Zsb29yJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IGdlbHUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlKGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oXG4gICAgICBjb250ZXh0LmlucHV0c1swXSxcbiAgICAgICdHZWx1JyxcbiAgICAgIChhKSA9PiBgMC41ICogJHthfSAqICgxLjAgKyBlcmZfdmYzMigke2F9ICogMC43MDcxMDY3ODExODY1NDc1KSlgLFxuICAgICAgZXJmSW1wbChkYXRhVHlwZSksXG4gICAgKSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBsZWFreVJlbHUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEFscGhhQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUpO1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLFxuICAgICAgJ0xlYWt5UmVsdScsXG4gICAgICAoYSkgPT4gYHNlbGVjdChsZWFreV9yZWx1X2FscGhhXyAqICR7YX0sICR7YX0sICR7YX0gPj0gdmVjNDwke2RhdGFUeXBlfT4oMC4wKSlgLFxuICAgICAgYGNvbnN0IGxlYWt5X3JlbHVfYWxwaGFfID0gJHtkYXRhVHlwZX0oJHthdHRyaWJ1dGVzLmFscGhhfSk7YCxcbiAgICAgIGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgKSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBub3QgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sICdOb3QnLCAoYSkgPT4gYCEke2F9YCkpO1xufTtcblxuZXhwb3J0IGNvbnN0IG5lZyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ05lZycsIChhKSA9PiBgLSR7YX1gKSk7XG59O1xuXG5leHBvcnQgY29uc3QgcmVjaXByb2NhbCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ1JlY2lwcm9jYWwnLCAoYSkgPT4gYDEuMC8ke2F9YCkpO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlbHUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlKGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oXG4gICAgICBjb250ZXh0LmlucHV0c1swXSxcbiAgICAgICdSZWx1JyxcbiAgICAgIChhKSA9PiBgc2VsZWN0KHZlYzQ8JHtkYXRhVHlwZX0+KDAuMCksICR7YX0sICR7YX0gPiB2ZWM0PCR7ZGF0YVR5cGV9PigwLjApKWAsXG4gICAgKSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBzaWdtb2lkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnU2lnbW9pZCcsIChhKSA9PiBgKDEuMCAvICgxLjAgKyBleHAoLSR7YX0pKSlgKSk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIEhhcmRTaWdtb2lkQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGFscGhhOiBudW1iZXI7XG4gIHJlYWRvbmx5IGJldGE6IG51bWJlcjtcbn1cblxuZXhwb3J0IGNvbnN0IHBhcnNlSGFyZFNpZ21vaWRBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogSGFyZFNpZ21vaWRBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleShcbiAgICBhdHRyaWJ1dGVzIGFzIHtcbiAgICAgIGFscGhhOiBudW1iZXI7XG4gICAgICBiZXRhOiBudW1iZXI7XG4gICAgfSxcbiAgKTtcblxuZXhwb3J0IGNvbnN0IGhhcmRTaWdtb2lkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBIYXJkU2lnbW9pZEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlKGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oXG4gICAgICBjb250ZXh0LmlucHV0c1swXSxcbiAgICAgICdIYXJkU2lnbW9pZCcsXG4gICAgICAoYSkgPT5cbiAgICAgICAgYG1heCh2ZWM0PCR7ZGF0YVR5cGV9PigwLjApLCBtaW4odmVjNDwke2RhdGFUeXBlfT4oMS4wKSwgJHthdHRyaWJ1dGVzLmFscGhhfSAqICR7YX0gKyB2ZWM0PCR7ZGF0YVR5cGV9Pigke2F0dHJpYnV0ZXMuYmV0YX0pKSlgLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgYXR0cmlidXRlcy5jYWNoZUtleSxcbiAgICApLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHNpbiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ1NpbicsICdzaW4nKSk7XG59O1xuXG5leHBvcnQgY29uc3Qgc2luaCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ1NpbmgnLCAnc2luaCcpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBzcXJ0ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnU3FydCcsICdzcXJ0JykpO1xufTtcblxuZXhwb3J0IGNvbnN0IHRhbiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ1RhbicsICd0YW4nKSk7XG59O1xuXG5leHBvcnQgY29uc3QgdGFuaEV4cHJlc3Npb24gPSAoYTogc3RyaW5nKSA9PiBgc2lnbigke2F9KSAqICgxIC0gZXhwKC0yICogYWJzKCR7YX0pKSkgLyAoMSArIGV4cCgtMiAqIGFicygke2F9KSkpYDtcblxuZXhwb3J0IGNvbnN0IHRhbmggPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgLy8gVE9ETzogcmV2aXNpdCBhZnRlciBodHRwczovL2dpdGh1Yi5jb20vZ3B1d2ViL2dwdXdlYi9pc3N1ZXMvNDQ1OCBpcyByZXNvbHZlZFxuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgJ1RhbmgnLCB0YW5oRXhwcmVzc2lvbikpO1xufTtcblxuZXhwb3J0IGNvbnN0IGZhc3RHZWx1SW1wbCA9ICh2YXJUeXBlID0gJ2YzMicpID0+IGBcbmNvbnN0IGZhc3RfZ2VsdV9hOiAke3ZhclR5cGV9ID0gMC41O1xuY29uc3QgZmFzdF9nZWx1X2I6ICR7dmFyVHlwZX0gPSAwLjc5Nzg4NDU2MDgwMjg2NTQ7XG5jb25zdCBmYXN0X2dlbHVfYzogJHt2YXJUeXBlfSA9IDAuMDM1Njc3NDA4MTM2MzAwMTI1O1xuXG5mbiB0YW5oX3YodjogdmVjNDwke3ZhclR5cGV9PikgLT4gdmVjNDwke3ZhclR5cGV9PiB7XG4gIHJldHVybiAke3RhbmhFeHByZXNzaW9uKCd2Jyl9O1xufVxuYDtcblxuZXhwb3J0IGNvbnN0IGZhc3RHZWx1RXhwcmVzc2lvbiA9ICh4OiBzdHJpbmcpID0+XG4gIGAoZmFzdF9nZWx1X2EgKyBmYXN0X2dlbHVfYSAqIHRhbmhfdigke3h9ICogKGZhc3RfZ2VsdV9jICogJHt4fSAqICR7eH0gKyBmYXN0X2dlbHVfYikpKSAqICR7eH1gO1xuXG5leHBvcnQgY29uc3QgZmFzdEdlbHUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsVmFsdWVUeXBlKGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8oXG4gICAgICBjb250ZXh0LmlucHV0c1swXSxcbiAgICAgICdGYXN0R2VsdScsXG4gICAgICBmYXN0R2VsdUV4cHJlc3Npb24sXG4gICAgICBmYXN0R2VsdUltcGwoZGF0YVR5cGUpLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUsXG4gICAgKSxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCB0aHJlc2hvbGRlZFJlbHUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEFscGhhQXR0cmlidXRlcyk6IG51bWJlciA9PiB7XG4gIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSk7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0sXG4gICAgICAnVGhyZXNob2xkZWRSZWx1JyxcbiAgICAgIChhKSA9PiBgc2VsZWN0KHZlYzQ8JHtkYXRhVHlwZX0+KDAuMCksICR7YX0sICR7YX0gPiB0aHJlc2hvbGRlZF9yZWx1X2FscGhhXylgLFxuICAgICAgYGNvbnN0IHRocmVzaG9sZGVkX3JlbHVfYWxwaGFfID0gdmVjNDwke2RhdGFUeXBlfT4oJHthdHRyaWJ1dGVzLmFscGhhfSk7YCxcbiAgICAgIGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgKSxcbiAgKTtcbiAgcmV0dXJuIDA7XG59O1xuXG5leHBvcnQgY29uc3QgbG9nID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCAnTG9nJywgJ2xvZycpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBxdWlja0dlbHVJbXBsID0gKHZhclR5cGU6IHN0cmluZywgYWxwaGE6IG51bWJlcikgPT4gYFxuY29uc3QgYWxwaGEgPSB2ZWM0PCR7dmFyVHlwZX0+KCR7YWxwaGF9KTtcbmNvbnN0IG9uZSA9ICR7dmFyVHlwZX0oMS4wKTtcbmNvbnN0IHplcm8gPSAke3ZhclR5cGV9KDAuMCk7XG5cbmZuIHF1aWNrX2dlbHVfaW1wbCh4OiB2ZWM0PCR7dmFyVHlwZX0+KSAtPiB2ZWM0PCR7dmFyVHlwZX0+IHtcbiAgbGV0IHYgPSB4ICphbHBoYTtcbiAgdmFyIHgxIDogdmVjNDwke3ZhclR5cGV9PjtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCA0OyBpID0gaSArIDEpIHtcbiAgICBpZiAodltpXSA+PSB6ZXJvKSB7XG4gICAgICB4MVtpXSA9IG9uZSAvIChvbmUgKyBleHAoLXZbaV0pKTtcbiAgICB9IGVsc2Uge1xuICAgICAgeDFbaV0gPSBvbmUgLSBvbmUgLyAob25lICsgZXhwKHZbaV0pKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHggKiB4MTtcbn1cbmA7XG5cbmV4cG9ydCBjb25zdCBxdWlja0dlbHVFeHByZXNzaW9uID0gKHg6IHN0cmluZykgPT4gYHF1aWNrX2dlbHVfaW1wbCgke3h9KWA7XG5cbmV4cG9ydCBjb25zdCBxdWlja2dlbHUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEFscGhhQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBkVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUoY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUpO1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mbyhcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLFxuICAgICAgJ1F1aWNrR2VsdScsXG4gICAgICBxdWlja0dlbHVFeHByZXNzaW9uLFxuICAgICAgcXVpY2tHZWx1SW1wbChkVHlwZSwgYXR0cmlidXRlcy5hbHBoYSksXG4gICAgICBhdHRyaWJ1dGVzLmNhY2hlS2V5LFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUsXG4gICAgKSxcbiAgKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbyB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciwgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlIH0gZnJvbSAnLi9jb21tb24nO1xuaW1wb3J0IHsgZXJmSW1wbCB9IGZyb20gJy4vdW5hcnktb3AnO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoICE9PSAzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCBzaG91bGQgaGF2ZSAzIGRpbWVuc2lvbnMnKTtcbiAgfVxuXG4gIGlmICghWzI1NjAsIDUxMjAsIDEwMjQwXS5pbmNsdWRlcyhpbnB1dHNbMF0uZGltc1syXSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2hpZGRlbiBzdGF0ZSBzaG91bGQgYmUgMjU2MCwgNTEyMCBvciAxMDI0MCcpO1xuICB9XG5cbiAgaWYgKGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignYmlhcyBpcyBleHBlY3RlZCB0byBoYXZlIDEgZGltZW5zaW9ucycpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS5kaW1zWzJdICE9PSBpbnB1dHNbMV0uZGltc1swXSkge1xuICAgIHRocm93IG5ldyBFcnJvcignbGFzdCBkaW1lbnNpb24gb2YgaW5wdXQgYW5kIGJpYXMgYXJlIG5vdCB0aGUgc2FtZScpO1xuICB9XG59O1xuXG5jb25zdCBjcmVhdGVCaWFzU3BsaXRHZWx1UHJvZ3JhbUluZm8gPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXMuc2xpY2UoKTtcbiAgb3V0cHV0U2hhcGVbMl0gPSBvdXRwdXRTaGFwZVsyXSAvIDI7XG5cbiAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMsIDQpO1xuICBjb25zdCBiaWFzID0gaW5wdXRWYXJpYWJsZSgnYmlhcycsIGlucHV0c1swXS5kYXRhVHlwZSwgW2lucHV0c1swXS5kaW1zWzJdXSwgNCk7XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLCA0KTtcblxuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gNDtcbiAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUoaW5wdXRzWzBdLmRhdGFUeXBlKTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcbiAgY29uc3QgTV9TUVJUMiA9IHNxcnQoMi4wKTtcbiAgY29uc3QgaGFsZkNoYW5uZWxzID0gJHtpbnB1dHNbMF0uZGltc1syXSAvIDQgLyAyfXU7XG5cbiAgJHtzaGFkZXJIZWxwZXIuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgYmlhcywgb3V0cHV0KX1cblxuICAke2VyZkltcGwoZGF0YVR5cGUpfVxuXG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMob3V0cHV0U2l6ZSl9XG4gICAgbGV0IGJpYXNJZHggPSBnbG9iYWxfaWR4ICUgaGFsZkNoYW5uZWxzO1xuICAgIGxldCBiYXRjaEluZGV4ID0gZ2xvYmFsX2lkeCAvIGhhbGZDaGFubmVscztcbiAgICBsZXQgaW5wdXRPZmZzZXQgPSBiaWFzSWR4ICsgYmF0Y2hJbmRleCAqIGhhbGZDaGFubmVscyAqIDI7XG4gICAgbGV0IHZhbHVlTGVmdCA9IGlucHV0W2lucHV0T2Zmc2V0XSArIGJpYXNbYmlhc0lkeF07XG4gICAgbGV0IHZhbHVlUmlnaHQgPSBpbnB1dFtpbnB1dE9mZnNldCArIGhhbGZDaGFubmVsc10gKyBiaWFzW2JpYXNJZHggKyBoYWxmQ2hhbm5lbHNdO1xuICAgIGxldCBnZWx1UmlnaHQgPSB2YWx1ZVJpZ2h0ICogMC41ICogKGVyZl92ZjMyKHZhbHVlUmlnaHQgLyBNX1NRUlQyKSArIDEpO1xuXG4gICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAndmFsdWVMZWZ0ICogZ2VsdVJpZ2h0Jyl9XG4gIH1gO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0JpYXNTcGxpdEdlbHUnLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgYmlhc1NwbGl0R2VsdSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVCaWFzU3BsaXRHZWx1UHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMpKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IEJyb2FkY2FzdFV0aWwsIFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcywgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciB9IGZyb20gJy4vY29tbW9uJztcblxudHlwZSBCdWlsdGluRnVuY3Rpb25OYW1lID0gc3RyaW5nO1xudHlwZSBCaW5hcnlDdXN0b21FeHByZXNzaW9uID0gKGV4cHJlc3Npb25BOiBzdHJpbmcsIGV4cHJlc3Npb25COiBzdHJpbmcpID0+IHN0cmluZztcbnR5cGUgQmluYXJ5RnVuY3Rpb25DYWxsID1cbiAgfCBCdWlsdGluRnVuY3Rpb25OYW1lXG4gIHwgQmluYXJ5Q3VzdG9tRXhwcmVzc2lvblxuICB8IHtcbiAgICAgIHNjYWxhcjogQmluYXJ5Q3VzdG9tRXhwcmVzc2lvbjtcbiAgICAgIHZlY3RvcjogQmluYXJ5Q3VzdG9tRXhwcmVzc2lvbjtcbiAgICB9O1xuXG5jb25zdCBjcmVhdGVCaW5hcnlPcFByb2dyYW1TaGFkZXIgPSAoXG4gIHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyLFxuICBkaW1zQTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGRpbXNCOiByZWFkb25seSBudW1iZXJbXSxcbiAgZGltc091dHB1dDogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHZlY3Rvcml6ZTogYm9vbGVhbixcbiAgZG9Ccm9hZGNhc3Q6IGJvb2xlYW4sXG4gIHNoYXJlZERpbWVuc2lvbkRpdmlzaWJsZUJ5NDogYm9vbGVhbixcbiAgZnVuY0NhbGw6IEJpbmFyeUZ1bmN0aW9uQ2FsbCxcbiAgdHlwZUE6IG51bWJlcixcbiAgdHlwZUI6IG51bWJlcixcbiAgdHlwZU91dHB1dDogbnVtYmVyLFxuICBhZGRpdGlvbmFsSW1wbGVtZW50YXRpb24/OiBzdHJpbmcsXG4pID0+IHtcbiAgbGV0IGV4cHJlc3Npb25TY2FsYXI6IEJpbmFyeUN1c3RvbUV4cHJlc3Npb247XG4gIGxldCBleHByZXNzaW9uVmVjdG9yOiBCaW5hcnlDdXN0b21FeHByZXNzaW9uO1xuICBpZiAodHlwZW9mIGZ1bmNDYWxsID09PSAnc3RyaW5nJykge1xuICAgIGV4cHJlc3Npb25TY2FsYXIgPSBleHByZXNzaW9uVmVjdG9yID0gKGEsIGIpID0+IGAke2Z1bmNDYWxsfSgoJHthfSksKCR7Yn0pKWA7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGZ1bmNDYWxsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgZXhwcmVzc2lvblNjYWxhciA9IGV4cHJlc3Npb25WZWN0b3IgPSBmdW5jQ2FsbDtcbiAgfSBlbHNlIHtcbiAgICBleHByZXNzaW9uU2NhbGFyID0gZnVuY0NhbGwuc2NhbGFyO1xuICAgIGV4cHJlc3Npb25WZWN0b3IgPSBmdW5jQ2FsbC52ZWN0b3I7XG4gIH1cblxuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0RGF0YScsIHR5cGVPdXRwdXQsIGRpbXNPdXRwdXQubGVuZ3RoLCA0KTtcbiAgY29uc3QgYSA9IGlucHV0VmFyaWFibGUoJ2FEYXRhJywgdHlwZUEsIGRpbXNBLmxlbmd0aCwgNCk7XG4gIGNvbnN0IGIgPSBpbnB1dFZhcmlhYmxlKCdiRGF0YScsIHR5cGVCLCBkaW1zQi5sZW5ndGgsIDQpO1xuXG4gIGxldCBhc3NpZ25tZW50OiBzdHJpbmc7XG4gIGlmICh2ZWN0b3JpemUpIHtcbiAgICBpZiAoZG9Ccm9hZGNhc3QpIHtcbiAgICAgIGNvbnN0IGlzQU9uZUVsZW1lbnQgPSBTaGFwZVV0aWwuc2l6ZShkaW1zQSkgPT09IDE7XG4gICAgICBjb25zdCBpc0JPbmVFbGVtZW50ID0gU2hhcGVVdGlsLnNpemUoZGltc0IpID09PSAxO1xuICAgICAgY29uc3QgYUxhc3REaW1EaXZpc2libGVCeTQgPSBkaW1zQS5sZW5ndGggPiAwICYmIGRpbXNBW2RpbXNBLmxlbmd0aCAtIDFdICUgNCA9PT0gMDtcbiAgICAgIGNvbnN0IGJMYXN0RGltRGl2aXNpYmxlQnk0ID0gZGltc0IubGVuZ3RoID4gMCAmJiBkaW1zQltkaW1zQi5sZW5ndGggLSAxXSAlIDQgPT09IDA7XG4gICAgICBpZiAoaXNBT25lRWxlbWVudCB8fCBpc0JPbmVFbGVtZW50KSB7XG4gICAgICAgIGFzc2lnbm1lbnQgPSBvdXRwdXQuc2V0QnlPZmZzZXQoXG4gICAgICAgICAgJ2dsb2JhbF9pZHgnLFxuICAgICAgICAgIGV4cHJlc3Npb25WZWN0b3IoXG4gICAgICAgICAgICBpc0FPbmVFbGVtZW50ID8gYCR7YS50eXBlLnZhbHVlfSgke2EuZ2V0QnlPZmZzZXQoJzAnKX0ueClgIDogYS5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpLFxuICAgICAgICAgICAgaXNCT25lRWxlbWVudCA/IGAke2IudHlwZS52YWx1ZX0oJHtiLmdldEJ5T2Zmc2V0KCcwJyl9LngpYCA6IGIuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKSxcbiAgICAgICAgICApLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXNzaWdubWVudCA9IGBcbiAgICAgICAgICAgIGxldCBvdXRwdXRJbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4ICogNHUnKX07XG4gICAgICAgICAgICBsZXQgb2Zmc2V0QSA9ICR7YS5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldCgnb3V0cHV0SW5kaWNlcycsIG91dHB1dCl9O1xuICAgICAgICAgICAgbGV0IG9mZnNldEIgPSAke2IuYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQoJ291dHB1dEluZGljZXMnLCBvdXRwdXQpfTtcbiAgICAgICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KFxuICAgICAgICAgICAgICAnZ2xvYmFsX2lkeCcsXG4gICAgICAgICAgICAgIGV4cHJlc3Npb25WZWN0b3IoXG4gICAgICAgICAgICAgICAgc2hhcmVkRGltZW5zaW9uRGl2aXNpYmxlQnk0IHx8IGFMYXN0RGltRGl2aXNpYmxlQnk0XG4gICAgICAgICAgICAgICAgICA/IGEuZ2V0QnlPZmZzZXQoJ29mZnNldEEgLyA0dScpXG4gICAgICAgICAgICAgICAgICA6IGAke2EudHlwZS52YWx1ZX0oJHthLmdldEJ5T2Zmc2V0KCdvZmZzZXRBIC8gNHUnKX1bb2Zmc2V0QSAlIDR1XSlgLFxuICAgICAgICAgICAgICAgIHNoYXJlZERpbWVuc2lvbkRpdmlzaWJsZUJ5NCB8fCBiTGFzdERpbURpdmlzaWJsZUJ5NFxuICAgICAgICAgICAgICAgICAgPyBiLmdldEJ5T2Zmc2V0KCdvZmZzZXRCIC8gNHUnKVxuICAgICAgICAgICAgICAgICAgOiBgJHtiLnR5cGUudmFsdWV9KCR7Yi5nZXRCeU9mZnNldCgnb2Zmc2V0QiAvIDR1Jyl9W29mZnNldEIgJSA0dV0pYCxcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICl9XG4gICAgICAgICAgYDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgYXNzaWdubWVudCA9IG91dHB1dC5zZXRCeU9mZnNldChcbiAgICAgICAgJ2dsb2JhbF9pZHgnLFxuICAgICAgICBleHByZXNzaW9uVmVjdG9yKGEuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKSwgYi5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpKSxcbiAgICAgICk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmICghZG9Ccm9hZGNhc3QpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbm8gbmVjZXNzYXJ5IHRvIHVzZSBzY2FsYXIgaW1wbGVtZW50YXRpb24gZm9yIGVsZW1lbnQtd2lzZSBiaW5hcnkgb3AgaW1wbGVtZW50YXRpb24uJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2luZ2xlQXNzaWdubWVudCA9IChyZXNTdHI6IHN0cmluZywgeDogbnVtYmVyLCB0eXBlQ2FzdCA9ICcnKSA9PiB7XG4gICAgICBjb25zdCBleHByZXNzaW9uQSA9IGBhRGF0YVtpbmRleEEke3h9XVtjb21wb25lbnRBJHt4fV1gO1xuICAgICAgY29uc3QgZXhwcmVzc2lvbkIgPSBgYkRhdGFbaW5kZXhCJHt4fV1bY29tcG9uZW50QiR7eH1dYDtcbiAgICAgIHJldHVybiBgXG4gICAgICAgICAgICBsZXQgb3V0cHV0SW5kaWNlcyR7eH0gPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoYGdsb2JhbF9pZHggKiA0dSArICR7eH11YCl9O1xuICAgICAgICAgICAgbGV0IG9mZnNldEEke3h9ID0gJHthLmJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0KGBvdXRwdXRJbmRpY2VzJHt4fWAsIG91dHB1dCl9O1xuICAgICAgICAgICAgbGV0IG9mZnNldEIke3h9ID0gJHtiLmJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0KGBvdXRwdXRJbmRpY2VzJHt4fWAsIG91dHB1dCl9O1xuICAgICAgICAgICAgbGV0IGluZGV4QSR7eH0gPSBvZmZzZXRBJHt4fSAvIDR1O1xuICAgICAgICAgICAgbGV0IGluZGV4QiR7eH0gPSBvZmZzZXRCJHt4fSAvIDR1O1xuICAgICAgICAgICAgbGV0IGNvbXBvbmVudEEke3h9ID0gb2Zmc2V0QSR7eH0gJSA0dTtcbiAgICAgICAgICAgIGxldCBjb21wb25lbnRCJHt4fSA9IG9mZnNldEIke3h9ICUgNHU7XG4gICAgICAgICAgICAke3Jlc1N0cn1bJHt4fV0gPSAke3R5cGVDYXN0fSgke2V4cHJlc3Npb25TY2FsYXIoZXhwcmVzc2lvbkEsIGV4cHJlc3Npb25CKX0pO1xuICAgICAgICAgIGA7XG4gICAgfTtcbiAgICBpZiAodHlwZU91dHB1dCA9PT0gRGF0YVR5cGUuYm9vbCkge1xuICAgICAgYXNzaWdubWVudCA9IGBcbiAgICAgICAgICAgIHZhciBkYXRhID0gdmVjNDx1MzI+KDApO1xuICAgICAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdkYXRhJywgMCwgJ3UzMicpfVxuICAgICAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdkYXRhJywgMSwgJ3UzMicpfVxuICAgICAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdkYXRhJywgMiwgJ3UzMicpfVxuICAgICAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdkYXRhJywgMywgJ3UzMicpfVxuICAgICAgICAgICAgb3V0cHV0RGF0YVtnbG9iYWxfaWR4XSA9IGRvdCh2ZWM0PHUzMj4oMHgxLCAweDEwMCwgMHgxMDAwMCwgMHgxMDAwMDAwKSwgdmVjNDx1MzI+KGRhdGEpKTtgO1xuICAgIH0gZWxzZSB7XG4gICAgICBhc3NpZ25tZW50ID0gYFxuICAgICAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdvdXRwdXREYXRhW2dsb2JhbF9pZHhdJywgMCl9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ291dHB1dERhdGFbZ2xvYmFsX2lkeF0nLCAxKX1cbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnb3V0cHV0RGF0YVtnbG9iYWxfaWR4XScsIDIpfVxuICAgICAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdvdXRwdXREYXRhW2dsb2JhbF9pZHhdJywgMyl9XG4gICAgICAgICAgYDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYFxuICAgICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ3ZlY19zaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMoYSwgYiwgb3V0cHV0KX1cblxuICAgICAgICAke2FkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbiA/PyAnJ31cblxuICAgICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMudmVjX3NpemUnKX1cbiAgICAgICAgJHthc3NpZ25tZW50fVxuICAgICAgfWA7XG59O1xuXG5jb25zdCBjcmVhdGVCaW5hcnlPcFByb2dyYW1JbmZvID0gKFxuICBuYW1lOiBzdHJpbmcsXG4gIGNhY2hlS2V5OiBzdHJpbmcsXG4gIGE6IFRlbnNvclZpZXcsXG4gIGI6IFRlbnNvclZpZXcsXG4gIGZ1bmNDYWxsOiBCaW5hcnlGdW5jdGlvbkNhbGwsXG4gIGFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbj86IHN0cmluZyxcbiAgb3V0cHV0RGF0YVR5cGU6IG51bWJlciA9IGEuZGF0YVR5cGUsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGFEaW1zID0gYS5kaW1zLm1hcCgoeCkgPT4gTnVtYmVyKHgpID8/IDEpO1xuICBjb25zdCBiRGltcyA9IGIuZGltcy5tYXAoKHgpID0+IE51bWJlcih4KSA/PyAxKTtcbiAgY29uc3QgaXNCcm9hZGNhc3QgPSAhU2hhcGVVdGlsLmFyZUVxdWFsKGFEaW1zLCBiRGltcyk7XG4gIGxldCBvdXRwdXRTaGFwZSA9IGFEaW1zO1xuICBsZXQgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKGFEaW1zKTtcblxuICBsZXQgdmVjdG9yaXplID0gZmFsc2U7XG4gIGxldCBzaGFyZWREaW1lbnNpb25EaXZpc2libGVCeTQgPSBmYWxzZTtcblxuICAvLyBUT0RPOiBkZWFsIHdpdGggemVyby1zaXplZCB0ZW5zb3JzIChlZy4gZGltcz1bMSwwXSlcbiAgY29uc3QgY2FjaGVLZXlBdXggPSBbaXNCcm9hZGNhc3RdO1xuICBpZiAoaXNCcm9hZGNhc3QpIHtcbiAgICBjb25zdCBjYWxjdWxhdGVkU2hhcGUgPSBCcm9hZGNhc3RVdGlsLmNhbGNTaGFwZShhRGltcywgYkRpbXMsIGZhbHNlKTtcbiAgICBpZiAoIWNhbGN1bGF0ZWRTaGFwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgcGVyZm9ybSBiaW5hcnkgb3Agb24gdGhlIGdpdmVuIHRlbnNvcnNcIik7XG4gICAgfVxuICAgIG91dHB1dFNoYXBlID0gY2FsY3VsYXRlZFNoYXBlLnNsaWNlKCk7XG4gICAgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgICBjb25zdCBpc0FPbmVFbGVtZW50ID0gU2hhcGVVdGlsLnNpemUoYURpbXMpID09PSAxO1xuICAgIGNvbnN0IGlzQk9uZUVsZW1lbnQgPSBTaGFwZVV0aWwuc2l6ZShiRGltcykgPT09IDE7XG4gICAgY29uc3QgYUxhc3REaW1EaXZpc2libGVCeTQgPSBhRGltcy5sZW5ndGggPiAwICYmIGFEaW1zW2FEaW1zLmxlbmd0aCAtIDFdICUgNCA9PT0gMDtcbiAgICBjb25zdCBiTGFzdERpbURpdmlzaWJsZUJ5NCA9IGJEaW1zLmxlbmd0aCA+IDAgJiYgYkRpbXNbYkRpbXMubGVuZ3RoIC0gMV0gJSA0ID09PSAwO1xuICAgIGNhY2hlS2V5QXV4LnB1c2goaXNBT25lRWxlbWVudCk7XG4gICAgY2FjaGVLZXlBdXgucHVzaChpc0JPbmVFbGVtZW50KTtcbiAgICBjYWNoZUtleUF1eC5wdXNoKGFMYXN0RGltRGl2aXNpYmxlQnk0KTtcbiAgICBjYWNoZUtleUF1eC5wdXNoKGJMYXN0RGltRGl2aXNpYmxlQnk0KTtcbiAgICAvLyBjaGVjayB3aGV0aGVyIHZlY3Rvcml6ZSBjYW4gYmUgZW5hYmxlZFxuICAgIGxldCBzaGFyZWREaW1lbnNpb24gPSAxO1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgb3V0cHV0U2hhcGUubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGRpbUEgPSBhRGltc1thRGltcy5sZW5ndGggLSBpXTtcbiAgICAgIGNvbnN0IGRpbUIgPSBiRGltc1tiRGltcy5sZW5ndGggLSBpXTtcbiAgICAgIGlmIChkaW1BID09PSBkaW1CKSB7XG4gICAgICAgIHNoYXJlZERpbWVuc2lvbiAqPSBkaW1BO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChzaGFyZWREaW1lbnNpb24gJSA0ID09PSAwKSB7XG4gICAgICBzaGFyZWREaW1lbnNpb25EaXZpc2libGVCeTQgPSB0cnVlO1xuICAgICAgdmVjdG9yaXplID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKGlzQU9uZUVsZW1lbnQgfHwgaXNCT25lRWxlbWVudCB8fCBhTGFzdERpbURpdmlzaWJsZUJ5NCB8fCBiTGFzdERpbURpdmlzaWJsZUJ5NCkge1xuICAgICAgdmVjdG9yaXplID0gdHJ1ZTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gZWxlbWVudC13aXNlXG4gICAgdmVjdG9yaXplID0gdHJ1ZTtcbiAgfVxuICBjYWNoZUtleUF1eC5wdXNoKHZlY3Rvcml6ZSk7XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBjYWNoZUtleSArIGNhY2hlS2V5QXV4Lm1hcCgoeCkgPT4geC50b1N0cmluZygpKS5qb2luKCdfJyksXG4gICAgICBpbnB1dERlcGVuZGVuY2llczogWydyYW5rJywgJ3JhbmsnXSxcbiAgICB9LFxuICAgIGdldFNoYWRlclNvdXJjZTogKHNoYWRlckhlbHBlcikgPT5cbiAgICAgIGNyZWF0ZUJpbmFyeU9wUHJvZ3JhbVNoYWRlcihcbiAgICAgICAgc2hhZGVySGVscGVyLFxuICAgICAgICBhRGltcyxcbiAgICAgICAgYkRpbXMsXG4gICAgICAgIG91dHB1dFNoYXBlLFxuICAgICAgICB2ZWN0b3JpemUsXG4gICAgICAgIGlzQnJvYWRjYXN0LFxuICAgICAgICBzaGFyZWREaW1lbnNpb25EaXZpc2libGVCeTQsXG4gICAgICAgIGZ1bmNDYWxsLFxuICAgICAgICBhLmRhdGFUeXBlLFxuICAgICAgICBiLmRhdGFUeXBlLFxuICAgICAgICBvdXRwdXREYXRhVHlwZSxcbiAgICAgICAgYWRkaXRpb25hbEltcGxlbWVudGF0aW9uLFxuICAgICAgKSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBvdXRwdXREYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLyAvIDQgLyogY29tcG9uZW50IHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXM6IFtcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IE1hdGguY2VpbChTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyA0KSB9LFxuICAgICAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhhRGltcywgYkRpbXMsIG91dHB1dFNoYXBlKSxcbiAgICAgIF0sXG4gICAgfSksXG4gIH07XG59O1xuXG5jb25zdCBydW5CaW5hcnlPcCA9IChcbiAgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsXG4gIG5hbWU6IHN0cmluZyxcbiAgZnVuY0NhbGw6IEJpbmFyeUZ1bmN0aW9uQ2FsbCxcbiAgYWRkaXRpb25hbEltcGxlbWVudGF0aW9uPzogc3RyaW5nLFxuICBjYWNoZUtleT86IHN0cmluZyxcbiAgb3V0cHV0RGF0YVR5cGU/OiBudW1iZXIsXG4pOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKFxuICAgIGNyZWF0ZUJpbmFyeU9wUHJvZ3JhbUluZm8oXG4gICAgICBuYW1lLFxuICAgICAgY2FjaGVLZXkgPz8gJycsXG4gICAgICBjb250ZXh0LmlucHV0c1swXSxcbiAgICAgIGNvbnRleHQuaW5wdXRzWzFdLFxuICAgICAgZnVuY0NhbGwsXG4gICAgICBhZGRpdGlvbmFsSW1wbGVtZW50YXRpb24sXG4gICAgICBvdXRwdXREYXRhVHlwZSxcbiAgICApLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGFkZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBydW5CaW5hcnlPcChjb250ZXh0LCAnQWRkJywgKGEsIGIpID0+IGAke2F9KyR7Yn1gKTtcbn07XG5cbmV4cG9ydCBjb25zdCBkaXYgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgcnVuQmluYXJ5T3AoY29udGV4dCwgJ0RpdicsIChhLCBiKSA9PiBgJHthfS8ke2J9YCk7XG59O1xuXG5leHBvcnQgY29uc3QgZXF1YWwgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgcnVuQmluYXJ5T3AoXG4gICAgY29udGV4dCxcbiAgICAnRXF1YWwnLFxuICAgIHsgc2NhbGFyOiAoYSwgYikgPT4gYHUzMigke2F9PT0ke2J9KWAsIHZlY3RvcjogKGEsIGIpID0+IGB2ZWM0PHUzMj4oJHthfT09JHtifSlgIH0sXG4gICAgdW5kZWZpbmVkLFxuICAgIHVuZGVmaW5lZCxcbiAgICBEYXRhVHlwZS5ib29sLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IG11bCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBydW5CaW5hcnlPcChjb250ZXh0LCAnTXVsJywgKGEsIGIpID0+IGAke2F9KiR7Yn1gKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwb3cgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29uc3QgdHlwZSA9IGlucHV0VmFyaWFibGUoJ2lucHV0JywgY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUsIGNvbnRleHQuaW5wdXRzWzBdLmRpbXMpLnR5cGUudmFsdWU7XG4gIGNvbnN0IHJvdW5kU3RyID0gdHlwZSA9PT0gJ2kzMicgPyAncm91bmQnIDogJyc7XG4gIHJ1bkJpbmFyeU9wKFxuICAgIGNvbnRleHQsXG4gICAgJ1BvdycsXG4gICAgeyBzY2FsYXI6IChhLCBiKSA9PiBgcG93X2N1c3RvbSgke2F9LCR7Yn0pYCwgdmVjdG9yOiAoYSwgYikgPT4gYHBvd192ZWN0b3JfY3VzdG9tKCR7YX0sJHtifSlgIH0sXG4gICAgYFxuICAgIGZuIHBvd19jdXN0b20oYSA6ICR7dHlwZX0sIGIgOiAke3R5cGV9KSAtPiAke3R5cGV9IHtcbiAgICAgIGlmIChiID09ICR7dHlwZX0oMC4wKSkge1xuICAgICAgICByZXR1cm4gJHt0eXBlfSgxLjApO1xuICAgICAgfSBlbHNlIGlmIChhIDwgJHt0eXBlfSgwLjApICYmIGYzMihiKSAhPSBmbG9vcihmMzIoYikpKSB7XG4gICAgICAgIHJldHVybiAke3R5cGV9KHBvdyhmMzIoYSksIGYzMihiKSkpOyAvLyBOYU5cbiAgICAgIH1cbiAgICAgIHJldHVybiBzZWxlY3Qoc2lnbihhKSwgJHt0eXBlfSgxLjApLCByb3VuZChmMzIoYWJzKGIpICUgJHt0eXBlfSgyLjApKSkgIT0gMS4wKSAqICR7dHlwZX0oJHtyb3VuZFN0cn0ocG93KGYzMihhYnMoYSkpLCBmMzIoYikpKSk7XG4gICAgfVxuICAgIGZuIHBvd192ZWN0b3JfY3VzdG9tKGEgOiB2ZWM0PCR7dHlwZX0+LCBiIDogdmVjNDwke3R5cGV9PikgLT4gdmVjNDwke3R5cGV9PiB7XG4gICAgICAvLyBUT0RPOiBpbXBsZW1lbnQgdmVjdG9yaXplZCBwb3dcbiAgICAgIHJldHVybiB2ZWM0PCR7dHlwZX0+KHBvd19jdXN0b20oYS54LCBiLngpLCBwb3dfY3VzdG9tKGEueSwgYi55KSwgcG93X2N1c3RvbShhLnosIGIueiksIHBvd19jdXN0b20oYS53LCBiLncpKTtcbiAgICB9XG4gICAgICBgLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHN1YiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBydW5CaW5hcnlPcChjb250ZXh0LCAnU3ViJywgKGEsIGIpID0+IGAke2F9LSR7Yn1gKTtcbn07XG5cbmV4cG9ydCBjb25zdCBncmVhdGVyID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHJ1bkJpbmFyeU9wKFxuICAgIGNvbnRleHQsXG4gICAgJ0dyZWF0ZXInLFxuICAgIHsgc2NhbGFyOiAoYSwgYikgPT4gYHUzMigke2F9PiR7Yn0pYCwgdmVjdG9yOiAoYSwgYikgPT4gYHZlYzQ8dTMyPigke2F9PiR7Yn0pYCB9LFxuICAgIHVuZGVmaW5lZCxcbiAgICB1bmRlZmluZWQsXG4gICAgRGF0YVR5cGUuYm9vbCxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBsZXNzID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHJ1bkJpbmFyeU9wKFxuICAgIGNvbnRleHQsXG4gICAgJ0xlc3MnLFxuICAgIHsgc2NhbGFyOiAoYSwgYikgPT4gYHUzMigke2F9PCR7Yn0pYCwgdmVjdG9yOiAoYSwgYikgPT4gYHZlYzQ8dTMyPigke2F9PCR7Yn0pYCB9LFxuICAgIHVuZGVmaW5lZCxcbiAgICB1bmRlZmluZWQsXG4gICAgRGF0YVR5cGUuYm9vbCxcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBncmVhdGVyT3JFcXVhbCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBydW5CaW5hcnlPcChcbiAgICBjb250ZXh0LFxuICAgICdHcmVhdGVyT3JFcXVhbCcsXG4gICAgeyBzY2FsYXI6IChhLCBiKSA9PiBgdTMyKCR7YX0+PSR7Yn0pYCwgdmVjdG9yOiAoYSwgYikgPT4gYHZlYzQ8dTMyPigke2F9Pj0ke2J9KWAgfSxcbiAgICB1bmRlZmluZWQsXG4gICAgdW5kZWZpbmVkLFxuICAgIERhdGFUeXBlLmJvb2wsXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgbGVzc09yRXF1YWwgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgcnVuQmluYXJ5T3AoXG4gICAgY29udGV4dCxcbiAgICAnTGVzc09yRXF1YWwnLFxuICAgIHsgc2NhbGFyOiAoYSwgYikgPT4gYHUzMigke2F9PD0ke2J9KWAsIHZlY3RvcjogKGEsIGIpID0+IGB2ZWM0PHUzMj4oJHthfTw9JHtifSlgIH0sXG4gICAgdW5kZWZpbmVkLFxuICAgIHVuZGVmaW5lZCxcbiAgICBEYXRhVHlwZS5ib29sLFxuICApO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsIEluZGljZXNIZWxwZXIsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29uY2F0QXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGF4aXM6IG51bWJlcjtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF4aXM6IG51bWJlcik6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoIDwgMSkge1xuICAgIHRocm93IG5ldyBFcnJvcigndG9vIGZldyBpbnB1dHMnKTtcbiAgfVxuICBjb25zdCByZWZlcmVuY2VJbmRleCA9IDA7XG4gIGNvbnN0IHJlZmVyZW5jZUlucHV0ID0gaW5wdXRzW3JlZmVyZW5jZUluZGV4XTtcbiAgY29uc3QgaW5wdXRUeXBlID0gcmVmZXJlbmNlSW5wdXQuZGF0YVR5cGU7XG4gIGNvbnN0IGlucHV0UmFuayA9IHJlZmVyZW5jZUlucHV0LmRpbXMubGVuZ3RoO1xuICBpbnB1dHMuZm9yRWFjaCgoaW5wdXQsIGkpID0+IHtcbiAgICBpZiAoaSA9PT0gcmVmZXJlbmNlSW5kZXgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gbWFrZSBzdXJlIHR5cGVzIG9mIGFsbCBpbnB1dHMgbWF0Y2hcbiAgICBpZiAoaW5wdXQuZGF0YVR5cGUgIT09IGlucHV0VHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCB0ZW5zb3JzIHNob3VsZCBiZSBvbmUgdHlwZScpO1xuICAgIH1cbiAgICAvLyBtYWtlIHN1cmUgdGhlIGRpbWVuc2lvbmFsaXR5IG9mIGFsbCBpbnB1dHMgYXJlIHRoZSBzYW1lXG4gICAgaWYgKGlucHV0LmRpbXMubGVuZ3RoICE9PSBpbnB1dFJhbmspIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgdGVuc29ycyBzaG91bGQgaGF2ZSB0aGUgc2FtZSBzaGFwZScpO1xuICAgIH1cbiAgICBpbnB1dC5kaW1zLmZvckVhY2goKGRpbSwgaSkgPT4ge1xuICAgICAgaWYgKGkgIT09IGF4aXMgJiYgZGltICE9PSByZWZlcmVuY2VJbnB1dC5kaW1zW2ldKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignbm9uIGNvbmNhdCBkaW1lbnNpb25zIG11c3QgbWF0Y2gnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59O1xuXG5jb25zdCBjYWxjdWxhdGVJbnB1dEluZGV4SW1wbCA9IChudW1iZXJPZlRlbnNvcnM6IG51bWJlciwgc2l6ZUluQ29uY2F0QXhpc1N0cjogc3RyaW5nKTogc3RyaW5nID0+IGBcbiAgZm4gY2FsY3VsYXRlSW5wdXRJbmRleChpbmRleDogdTMyKSAtPiB1MzIge1xuICAgIGxldCBzaXplSW5Db25jYXRBeGlzID0gYXJyYXk8dTMyLCAke251bWJlck9mVGVuc29yc311Pigke3NpemVJbkNvbmNhdEF4aXNTdHJ9KTtcbiAgICBmb3IgKHZhciBpOiB1MzIgPSAwdTsgaSA8ICR7bnVtYmVyT2ZUZW5zb3JzfTsgaSArPSAxdSApIHtcbiAgICAgIGlmIChpbmRleCA8IHNpemVJbkNvbmNhdEF4aXNbaV0pIHtcbiAgICAgICAgcmV0dXJuIGk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAke251bWJlck9mVGVuc29yc311O1xuICB9YDtcblxuY29uc3QgYXNzaWduT3V0cHV0RGF0YSA9IChpbnB1dHM6IHJlYWRvbmx5IEluZGljZXNIZWxwZXJbXSwgb3V0cHV0OiBJbmRpY2VzSGVscGVyKSA9PiB7XG4gIGNvbnN0IG51bWJlck9mVGVuc29ycyA9IGlucHV0cy5sZW5ndGg7XG5cbiAgY29uc3QgY29kZUxpbmVzOiBzdHJpbmdbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlck9mVGVuc29yczsgKytpKSB7XG4gICAgY29uc3QgcmV0dXJuU25pcHBldCA9IG91dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsIGlucHV0c1tpXS5nZXRCeUluZGljZXMoJ2luZGljZXMnKSk7XG4gICAgaWYgKG51bWJlck9mVGVuc29ycyA9PT0gMSkge1xuICAgICAgY29kZUxpbmVzLnB1c2gocmV0dXJuU25pcHBldCk7XG4gICAgfSBlbHNlIGlmIChpID09PSAwKSB7XG4gICAgICBjb2RlTGluZXMucHVzaChgaWYgKGlucHV0SW5kZXggPT0gJHtpfXUpIHsgJHtyZXR1cm5TbmlwcGV0fSB9YCk7XG4gICAgfSBlbHNlIGlmIChpID09PSBudW1iZXJPZlRlbnNvcnMgLSAxKSB7XG4gICAgICBjb2RlTGluZXMucHVzaChgZWxzZSB7ICR7cmV0dXJuU25pcHBldH0gfWApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlTGluZXMucHVzaChgZWxzZSBpZiAoaW5wdXRJbmRleCA9PSAke2l9KSB7ICR7cmV0dXJuU25pcHBldH0gfWApO1xuICAgIH1cbiAgfVxuICByZXR1cm4gY29kZUxpbmVzLmpvaW4oJ1xcbicpO1xufTtcblxuY29uc3QgY3JlYXRlQ29uY2F0UHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhZGp1c3RlZEF4aXM6IG51bWJlcixcbiAgb3V0cHV0U2hhcGU6IG51bWJlcltdLFxuICBkYXRhVHlwZTogRGF0YVR5cGUsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG5cbiAgY29uc3Qgc2l6ZUluQ29uY2F0QXhpcyA9IG5ldyBBcnJheTxudW1iZXI+KGlucHV0cy5sZW5ndGgpO1xuICBjb25zdCBpbnB1dFZhcnMgPSBuZXcgQXJyYXk8SW5kaWNlc0hlbHBlcj4oaW5wdXRzLmxlbmd0aCk7XG5cbiAgbGV0IHByZXZpb3VzU3VtID0gMDtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbXTtcbiAgY29uc3QgaW5wdXRSYW5rcyA9IFtdO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfV07XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRzLmxlbmd0aDsgKytpKSB7XG4gICAgcHJldmlvdXNTdW0gKz0gaW5wdXRzW2ldLmRpbXNbYWRqdXN0ZWRBeGlzXTtcbiAgICBzaXplSW5Db25jYXRBeGlzW2ldID0gcHJldmlvdXNTdW07XG4gICAgaW5wdXRSYW5rcy5wdXNoKGlucHV0c1tpXS5kaW1zLmxlbmd0aCk7XG4gICAgaW5wdXRWYXJzW2ldID0gaW5wdXRWYXJpYWJsZShgaW5wdXQke2l9YCwgZGF0YVR5cGUsIGlucHV0UmFua3NbaV0pO1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3JhbmsnKTtcbiAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCh7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogc2l6ZUluQ29uY2F0QXhpc1tpXSB9KTtcbiAgfVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0cy5sZW5ndGg7ICsraSkge1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1tpXS5kaW1zKSk7XG4gIH1cbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0cHV0U2hhcGUpKTtcblxuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCk7XG4gIGNvbnN0IGluZGljZXNBeGlzID0gb3V0cHV0LmluZGljZXNHZXQoJ2luZGljZXMnLCBhZGp1c3RlZEF4aXMpO1xuICBjb25zdCBzaXplSW5Db25jYXRBeGlzU3RyID0gQXJyYXkuZnJvbShBcnJheShzaXplSW5Db25jYXRBeGlzLmxlbmd0aCkua2V5cygpKVxuICAgIC5tYXAoKGkpID0+IGB1bmlmb3Jtcy5zaXplSW5Db25jYXRBeGlzJHtpfWApXG4gICAgLmpvaW4oJywnKTtcbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG5cbiAgJHsoKCkgPT4ge1xuICAgIHNoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ291dHB1dFNpemUnLCAndTMyJyk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oYHNpemVJbkNvbmNhdEF4aXMke2l9YCwgJ3UzMicpO1xuICAgIH1cbiAgICByZXR1cm4gc2hhZGVySGVscGVyLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJzLCBvdXRwdXQpO1xuICB9KSgpfVxuXG4gICR7Y2FsY3VsYXRlSW5wdXRJbmRleEltcGwoc2l6ZUluQ29uY2F0QXhpcy5sZW5ndGgsIHNpemVJbkNvbmNhdEF4aXNTdHIpfVxuXG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dFNpemUnKX1cblxuICAgIHZhciBpbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuXG4gICAgbGV0IGlucHV0SW5kZXggPSBjYWxjdWxhdGVJbnB1dEluZGV4KCR7aW5kaWNlc0F4aXN9KTtcbiAgICBpZiAoaW5wdXRJbmRleCAhPSAwdSkge1xuICAgICAgbGV0IHNpemVJbkNvbmNhdEF4aXMgPSBhcnJheTx1MzIsICR7c2l6ZUluQ29uY2F0QXhpcy5sZW5ndGh9dT4oJHtzaXplSW5Db25jYXRBeGlzU3RyfSk7XG4gICAgICAke2luZGljZXNBeGlzfSAtPSBzaXplSW5Db25jYXRBeGlzW2lucHV0SW5kZXggLSAxdV07XG4gICAgfVxuXG4gICAgJHthc3NpZ25PdXRwdXREYXRhKGlucHV0VmFycywgb3V0cHV0KX1cbiAgfWA7XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQ29uY2F0JyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHthZGp1c3RlZEF4aXN9YCwgaW5wdXREZXBlbmRlbmNpZXMgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBjb25jYXQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IENvbmNhdEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgY29uc3QgaW5wdXRzID0gY29udGV4dC5pbnB1dHM7XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgYWRqdXN0ZWRBeGlzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4aXMoYXR0cmlidXRlcy5heGlzLCBpbnB1dFNoYXBlLmxlbmd0aCk7XG4gIHZhbGlkYXRlSW5wdXRzKGlucHV0cywgYWRqdXN0ZWRBeGlzKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dFNoYXBlLnNsaWNlKCk7XG4gIG91dHB1dFNoYXBlW2FkanVzdGVkQXhpc10gPSBpbnB1dHMucmVkdWNlKFxuICAgIChzdW0sIGlucHV0KSA9PiBzdW0gKyAoaW5wdXQuZGltcy5sZW5ndGggPiBhZGp1c3RlZEF4aXMgPyBpbnB1dC5kaW1zW2FkanVzdGVkQXhpc10gOiAwKSxcbiAgICAwLFxuICApO1xuICAvLyAwIGxlbmd0aCB0ZW5zb3JzIGFyZSB2YWxpZCBmb3IgY29uY2F0LCByZW1vdmUgdGhlbVxuICBjb25zdCBub25FbXB0eUlucHV0cyA9IGlucHV0cy5maWx0ZXIoKGlucHV0KSA9PiBTaGFwZVV0aWwuc2l6ZShpbnB1dC5kaW1zKSA+IDApO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlQ29uY2F0UHJvZ3JhbUluZm8obm9uRW1wdHlJbnB1dHMsIGFkanVzdGVkQXhpcywgb3V0cHV0U2hhcGUsIGlucHV0c1swXS5kYXRhVHlwZSksIHtcbiAgICBpbnB1dHM6IG5vbkVtcHR5SW5wdXRzLFxuICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUNvbmNhdEF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBDb25jYXRBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IGF4aXM6IGF0dHJpYnV0ZXMuYXhpcyBhcyBudW1iZXIgfSk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgTUFYX0NMSVAsIE1JTl9DTElQIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgVW5pZm9ybXNBcnJheVR5cGUgfSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyB7XG4gIHJlYWRvbmx5IGFjdGl2YXRpb246IHN0cmluZztcbiAgcmVhZG9ubHkgY2xpcE1pbj86IG51bWJlcjtcbiAgcmVhZG9ubHkgY2xpcE1heD86IG51bWJlcjtcbiAgcmVhZG9ubHkgYWxwaGE/OiBudW1iZXI7XG4gIHJlYWRvbmx5IGJldGE/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBnZXRBY3RpdmF0aW9uU25pcHBldCA9IChcbiAgYXR0cmlidXRlczogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyxcbiAgdmFsdWVUeXBlOiBzdHJpbmcsXG4gIGJhc2VUeXBlID0gJ2YzMicsXG4pOiBzdHJpbmcgPT4ge1xuICBzd2l0Y2ggKGF0dHJpYnV0ZXMuYWN0aXZhdGlvbikge1xuICAgIGNhc2UgJ1JlbHUnOlxuICAgICAgcmV0dXJuIGB2YWx1ZSA9IG1heCh2YWx1ZSwgJHt2YWx1ZVR5cGV9KDAuMCkpO2A7XG4gICAgY2FzZSAnU2lnbW9pZCc6XG4gICAgICByZXR1cm4gYHZhbHVlID0gKCR7dmFsdWVUeXBlfSgxLjApIC8gKCR7dmFsdWVUeXBlfSgxLjApICsgZXhwKC12YWx1ZSkpKTtgO1xuICAgIGNhc2UgJ0NsaXAnOlxuICAgICAgcmV0dXJuIGB2YWx1ZSA9IGNsYW1wKHZhbHVlLCAke3ZhbHVlVHlwZX0oJHtiYXNlVHlwZX0odW5pZm9ybXMuY2xpcF9taW4pKSwgJHt2YWx1ZVR5cGV9KCR7XG4gICAgICAgIGJhc2VUeXBlXG4gICAgICB9KHVuaWZvcm1zLmNsaXBfbWF4KSkpO2A7XG4gICAgY2FzZSAnSGFyZFNpZ21vaWQnOlxuICAgICAgcmV0dXJuIGB2YWx1ZSA9IG1heCgke3ZhbHVlVHlwZX0oMC4wKSwgbWluKCR7dmFsdWVUeXBlfSgxLjApLCAke2Jhc2VUeXBlfSh1bmlmb3Jtcy5hbHBoYSkgKiB2YWx1ZSArICR7XG4gICAgICAgIGJhc2VUeXBlXG4gICAgICB9KHVuaWZvcm1zLmJldGEpKSk7YDtcbiAgICBjYXNlICdMZWFreVJlbHUnOlxuICAgICAgcmV0dXJuIGB2YWx1ZSA9IHNlbGVjdCgke2Jhc2VUeXBlfSh1bmlmb3Jtcy5hbHBoYSkgKiB2YWx1ZSwgdmFsdWUsIHZhbHVlID49ICR7dmFsdWVUeXBlfSgwLjApKTtgO1xuICAgIGNhc2UgJ1RhbmgnOlxuICAgICAgcmV0dXJuIGBsZXQgZTJ4ID0gZXhwKC0yLjAgKiBhYnModmFsdWUpKTtcbiAgICAgICAgICAgICAgdmFsdWUgPSBzaWduKHZhbHVlKSAqICgxLjAgLSBlMngpIC8gKDEuMCArIGUyeCk7XG4gICAgICAgIGA7XG4gICAgY2FzZSAnJzpcbiAgICAgIHJldHVybiAnJztcbiAgICAvLyBUT0RPOiBhZGRpbmcgb3RoZXIgYWN0aXZhdGlvbnMgdGhhdCBjYW4gYmUgZnVzZWQuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgYWN0aXZhdGlvbiAke2F0dHJpYnV0ZXMuYWN0aXZhdGlvbn1gKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGFwcGVuZEFjdGl2YXRpb25Vbmlmb3Jtc0RhdGEgPSAoXG4gIGF0dHJpYnV0ZXM6IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMsXG4gIHByb2dyYW1Vbmlmb3JtOiBQcm9ncmFtVW5pZm9ybVtdLFxuKSA9PiB7XG4gIGlmIChhdHRyaWJ1dGVzLmFjdGl2YXRpb24gPT09ICdDbGlwJykge1xuICAgIHByb2dyYW1Vbmlmb3JtLnB1c2goXG4gICAgICB7IHR5cGU6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBhdHRyaWJ1dGVzLmNsaXBNYXghIH0sXG4gICAgICB7IHR5cGU6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBhdHRyaWJ1dGVzLmNsaXBNaW4hIH0sXG4gICAgKTtcbiAgfSBlbHNlIGlmIChhdHRyaWJ1dGVzLmFjdGl2YXRpb24gPT09ICdIYXJkU2lnbW9pZCcpIHtcbiAgICBwcm9ncmFtVW5pZm9ybS5wdXNoKFxuICAgICAgeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogYXR0cmlidXRlcy5hbHBoYSEgfSxcbiAgICAgIHsgdHlwZTogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IGF0dHJpYnV0ZXMuYmV0YSEgfSxcbiAgICApO1xuICB9IGVsc2UgaWYgKGF0dHJpYnV0ZXMuYWN0aXZhdGlvbiA9PT0gJ0xlYWt5UmVsdScpIHtcbiAgICBwcm9ncmFtVW5pZm9ybS5wdXNoKHsgdHlwZTogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IGF0dHJpYnV0ZXMuYWxwaGEhIH0pO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zID0gKGF0dHJpYnV0ZXM6IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMsIHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSkgPT4ge1xuICBpZiAoYXR0cmlidXRlcy5hY3RpdmF0aW9uID09PSAnQ2xpcCcpIHtcbiAgICB1bmlmb3Jtcy5wdXNoKHsgbmFtZTogJ2NsaXBfbWF4JywgdHlwZTogJ2YzMicgfSwgeyBuYW1lOiAnY2xpcF9taW4nLCB0eXBlOiAnZjMyJyB9KTtcbiAgfSBlbHNlIGlmIChhdHRyaWJ1dGVzLmFjdGl2YXRpb24gPT09ICdIYXJkU2lnbW9pZCcpIHtcbiAgICB1bmlmb3Jtcy5wdXNoKHsgbmFtZTogJ2FscGhhJywgdHlwZTogJ2YzMicgfSwgeyBuYW1lOiAnYmV0YScsIHR5cGU6ICdmMzInIH0pO1xuICB9IGVsc2UgaWYgKGF0dHJpYnV0ZXMuYWN0aXZhdGlvbiA9PT0gJ0xlYWt5UmVsdScpIHtcbiAgICB1bmlmb3Jtcy5wdXNoKHsgbmFtZTogJ2FscGhhJywgdHlwZTogJ2YzMicgfSk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMgPSAoXG4gIGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkLFxuKTogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGFjdGl2YXRpb24gPSAoYXR0cmlidXRlcz8uYWN0aXZhdGlvbiBhcyBzdHJpbmcpIHx8ICcnO1xuICBpZiAoYWN0aXZhdGlvbiA9PT0gJ0hhcmRTaWdtb2lkJykge1xuICAgIGNvbnN0IFthbHBoYSwgYmV0YV0gPSAoYXR0cmlidXRlcz8uYWN0aXZhdGlvbl9wYXJhbXMgYXMgW251bWJlciwgbnVtYmVyXSkgfHwgWzAuMiwgMC41XTtcbiAgICByZXR1cm4geyBhY3RpdmF0aW9uLCBhbHBoYSwgYmV0YSB9O1xuICB9IGVsc2UgaWYgKGFjdGl2YXRpb24gPT09ICdDbGlwJykge1xuICAgIGNvbnN0IFtjbGlwTWluLCBjbGlwTWF4XSA9IChhdHRyaWJ1dGVzPy5hY3RpdmF0aW9uX3BhcmFtcyBhcyBbbnVtYmVyLCBudW1iZXJdKSB8fCBbTUlOX0NMSVAsIE1BWF9DTElQXTtcbiAgICByZXR1cm4geyBhY3RpdmF0aW9uLCBjbGlwTWF4LCBjbGlwTWluIH07XG4gIH0gZWxzZSBpZiAoYWN0aXZhdGlvbiA9PT0gJ0xlYWt5UmVsdScpIHtcbiAgICBjb25zdCBbYWxwaGFdID0gKGF0dHJpYnV0ZXM/LmFjdGl2YXRpb25fcGFyYW1zIGFzIFtudW1iZXJdKSB8fCBbMC4wMV07XG4gICAgcmV0dXJuIHsgYWN0aXZhdGlvbiwgYWxwaGEgfTtcbiAgfVxuICByZXR1cm4geyBhY3RpdmF0aW9uIH07XG59O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuLy8gc2FtcGxlZCBmcm9tIFtAdGVuc29yZmxvdy90ZmpzXSB0ZmpzLWJhY2tlbmQtd2ViZ3B1L3NyYy9hY3RpdmF0aW9uX3V0aWwudHNcbi8vXG4vLyBtb2RpZmllZCB0byBmaXQgdGhlIG5lZWRzIG9mIHRoZSBwcm9qZWN0XG5cbmV4cG9ydCBjb25zdCB0eXBlU25pcHBldCA9IChjb21wb25lbnQ6IG51bWJlciwgZGF0YVR5cGU6IHN0cmluZykgPT4ge1xuICBzd2l0Y2ggKGNvbXBvbmVudCkge1xuICAgIGNhc2UgMTpcbiAgICAgIHJldHVybiBkYXRhVHlwZTtcbiAgICBjYXNlIDI6XG4gICAgICByZXR1cm4gYHZlYzI8JHtkYXRhVHlwZX0+YDtcbiAgICBjYXNlIDM6XG4gICAgICByZXR1cm4gYHZlYzM8JHtkYXRhVHlwZX0+YDtcbiAgICBjYXNlIDQ6XG4gICAgICByZXR1cm4gYHZlYzQ8JHtkYXRhVHlwZX0+YDtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbXBvbmVudH0tY29tcG9uZW50IGlzIG5vdCBzdXBwb3J0ZWQuYCk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBiaWFzU25pcHBldCA9IChoYXNCaWFzOiBib29sZWFuKTogc3RyaW5nID0+IGBcbiAgICAgICR7aGFzQmlhcyA/ICd2YWx1ZSA9IHZhbHVlICsgZ2V0Qmlhc0J5T3V0cHV0Q29vcmRzKGNvb3Jkcyk7JyA6ICcnfVxuICAgICAgYDtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbi8vIHNhbXBsZWQgZnJvbSBbQHRlbnNvcmZsb3cvdGZqc10gdGZqcy1jb3JlL3NyYy9vcHMvY29udl91dGlsLnRzXG4vL1xuLy8gbW9kaWZpZWQgdG8gZml0IHRoZSBuZWVkcyBvZiB0aGUgcHJvamVjdFxuXG5leHBvcnQgY29uc3QgdXRpbEZ1bmN0aW9ucyA9IChzdHJpZGVTdHI6IHN0cmluZykgPT4gYFxuZm4gZ2V0SW5kZXhGcm9tQ29vcmRzNEQoY29vcmRzIDogdmVjNDxpMzI+LCBzaGFwZSA6IHZlYzQ8aTMyPikgLT4gaTMyIHtcbiAgcmV0dXJuIGRvdChjb29yZHMsIHZlYzQ8aTMyPihcbiAgICAgIHNoYXBlLnkgKiBzaGFwZS56ICogc2hhcGUudywgc2hhcGUueiAqIHNoYXBlLncsIHNoYXBlLncsIDEpKTtcbn1cbmZuIGdldE91dHB1dEluZGV4RnJvbUNvb3Jkcyhjb29yZHMgOiB2ZWM0PGkzMj4pIC0+IGkzMiB7XG4gIHJldHVybiBkb3QoY29vcmRzLCB2ZWM0PGkzMj4oXG4gICAgaTMyKCR7c3RyaWRlU3RyfS54KSwgaTMyKCR7c3RyaWRlU3RyfS55KSwgaTMyKCR7c3RyaWRlU3RyfS56KSwgMSkpO1xufVxuYDtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBQcm9ncmFtSW5mbywgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBnZXRFbGVtZW50QXQsXG4gIGdldE1heENvbXBvbmVudHMsXG4gIEluZGljZXNIZWxwZXIsXG4gIGlucHV0VmFyaWFibGUsXG4gIGludGVybmFsVmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcbmltcG9ydCB7XG4gIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3JtcyxcbiAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zRGF0YSxcbiAgZ2V0QWN0aXZhdGlvblNuaXBwZXQsXG4gIEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMsXG59IGZyb20gJy4vZnVzZS11dGlscyc7XG5cbi8vIEhlbHBlciB0aGF0IGNvbnZlcnQgb3V0cHV0IGJhdGNoIGluZGljZXMgdG8gaW5wdXQgYmF0Y2ggaW5kaWNlcyB1c2luZyBvbmx5IHRoZSByYW5rIGFuZFxuLy8gdGhlIHNoYXBlIGluZm9ybWF0aW9uIGluIHVuaWZvcm1cbmV4cG9ydCBjb25zdCBjb252ZXJ0T3V0cHV0QmF0Y2hJbmRpY2VzVG9JbnB1dEJhdGNoSW5kaWNlcyA9IChcbiAgdGFyZ2V0SW5kaWNlc05hbWU6IHN0cmluZyxcbiAgaW5wdXRWYXJpYWJsZTogSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRCYXRjaFJhbms6IG51bWJlcixcbiAgb3V0cHV0QmF0Y2hSYW5rOiBudW1iZXIsXG4gIGJhdGNoSW5kaWNlc05hbWU6IHN0cmluZyxcbikgPT4ge1xuICAvLyBBc3N1bWUgb3V0cHV0QmF0Y2hSYW5rID49IGlucHV0QmF0Y2hSYW5rLCB0aGUgZmlyc3Qgb3V0cHV0QmF0Y2hSYW5rIC0gaW5wdXRCYXRjaFJhbmsgb2ZcbiAgLy8gb3V0cHV0QmF0Y2hSYW5rIHNob3VsZCBiZSBpZ25vcmVkLlxuICBjb25zdCBleHRlbmRpbmdJbnB1dFJhbmsgPSBvdXRwdXRCYXRjaFJhbmsgLSBpbnB1dEJhdGNoUmFuaztcbiAgcmV0dXJuIGBcbiAgICAgICR7QXJyYXkuZnJvbSh7IGxlbmd0aDogaW5wdXRCYXRjaFJhbmsgfSlcbiAgICAgICAgLm1hcChcbiAgICAgICAgICAoXywgaSkgPT4gYFxuICAgICAgaWYgKCR7Z2V0RWxlbWVudEF0KGlucHV0VmFyaWFibGUuc2hhcGUsIGksIGlucHV0VmFyaWFibGUucmFuayl9ICE9IDEpIHtcbiAgICAgICAgJHtpbnB1dFZhcmlhYmxlLmluZGljZXNTZXQodGFyZ2V0SW5kaWNlc05hbWUsIGksIGdldEVsZW1lbnRBdChiYXRjaEluZGljZXNOYW1lLCBpICsgZXh0ZW5kaW5nSW5wdXRSYW5rLCBvdXRwdXRCYXRjaFJhbmspKX1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgICR7aW5wdXRWYXJpYWJsZS5pbmRpY2VzU2V0KHRhcmdldEluZGljZXNOYW1lLCBpLCAwKX1cbiAgICAgIH1gLFxuICAgICAgICApXG4gICAgICAgIC5qb2luKCcnKX1cbmA7XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlTmFpdmVNYXRtdWxQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGFjdGl2YXRpb25BdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzLFxuICBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHJlc2hhcGVkT3V0cHV0U2hhcGU/OiByZWFkb25seSBudW1iZXJbXSxcbiAgaXNDaGFubmVsc0xhc3QgPSBmYWxzZSAvKiBvbmx5IHVzZWQgZm9yIGNvbnYyZEJ5TWF0TXVsKi8sXG4gIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uPzogKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSkgPT4gbnVtYmVyW10sXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGFTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBiU2hhcGUgPSBpbnB1dHNbMV0uZGltcztcblxuICBjb25zdCBNID0gYVNoYXBlW2FTaGFwZS5sZW5ndGggLSAyXTtcbiAgY29uc3QgTiA9IGJTaGFwZVtiU2hhcGUubGVuZ3RoIC0gMV07XG4gIGNvbnN0IEsgPSBhU2hhcGVbYVNoYXBlLmxlbmd0aCAtIDFdO1xuICBjb25zdCBjb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhOKTtcbiAgY29uc3QgYUNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKEspO1xuICBjb25zdCBvdXRwdXROdW1iZXIgPSBnZXRNYXhDb21wb25lbnRzKE0pO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gY29tcG9uZW50cyAvIG91dHB1dE51bWJlcjtcbiAgY29uc3QgaGFzQmlhcyA9IGlucHV0cy5sZW5ndGggPiAyO1xuICBjb25zdCBvdXRlckRpbXMgPSByZXNoYXBlZE91dHB1dFNoYXBlID8gcmVzaGFwZWRPdXRwdXRTaGFwZS5zbGljZSgwLCAtMikgOiBvdXRwdXRTaGFwZS5zbGljZSgwLCAtMik7XG4gIGNvbnN0IGJhdGNoU2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dGVyRGltcyk7XG4gIGNvbnN0IG91dHB1dFNoYXBlSW5TaGFkZXIgPSBbYmF0Y2hTaXplLCBNLCBOXTtcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogTSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBOIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IEsgfSxcbiAgXTtcbiAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zRGF0YShhY3RpdmF0aW9uQXR0cmlidXRlcywgcHJvZ3JhbVVuaWZvcm1zKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0ZXJEaW1zLCBhU2hhcGUsIGJTaGFwZSkpO1xuICBpZiAoaGFzQmlhcykge1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1syXS5kaW1zKSk7XG4gIH1cbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0cHV0U2hhcGVJblNoYWRlcikpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGJhdGNoRGltcyA9IGludGVybmFsVmFyaWFibGUoJ2JhdGNoX2RpbXMnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dGVyRGltcy5sZW5ndGgpO1xuICAgIGNvbnN0IGEgPSBpbnB1dFZhcmlhYmxlKCdhJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBhU2hhcGUubGVuZ3RoLCBhQ29tcG9uZW50cyk7XG4gICAgY29uc3QgYiA9IGlucHV0VmFyaWFibGUoJ2InLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGJTaGFwZS5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlSW5TaGFkZXIubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBiYXNlVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShvdXRwdXQudHlwZS50ZW5zb3IpO1xuICAgIGNvbnN0IGFwcGx5QWN0aXZhdGlvbiA9IGdldEFjdGl2YXRpb25TbmlwcGV0KGFjdGl2YXRpb25BdHRyaWJ1dGVzLCBvdXRwdXQudHlwZS52YWx1ZSwgYmFzZVR5cGUpO1xuICAgIGNvbnN0IGlucHV0VmFyaWFibGVzID0gW2EsIGJdO1xuICAgIGxldCBwcm9jZXNzQmlhcyA9ICcnO1xuICAgIGlmIChoYXNCaWFzKSB7XG4gICAgICBjb25zdCBiaWFzQ29tcG9uZW50cyA9IGlzQ2hhbm5lbHNMYXN0ID8gY29tcG9uZW50cyA6IDE7XG4gICAgICBpbnB1dFZhcmlhYmxlcy5wdXNoKGlucHV0VmFyaWFibGUoJ2JpYXMnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLmxlbmd0aCwgYmlhc0NvbXBvbmVudHMpKTtcbiAgICAgIHByb2Nlc3NCaWFzID0gYCR7XG4gICAgICAgIGlzQ2hhbm5lbHNMYXN0ID8gYHZhbHVlICs9IGJpYXNbY29sIC8gJHtiaWFzQ29tcG9uZW50c31dO2AgOiBgdmFsdWUgKz0gJHtvdXRwdXQudHlwZS52YWx1ZX0oYmlhc1tyb3cgKyBpXSk7YFxuICAgICAgfWA7XG4gICAgfVxuXG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnb3V0cHV0X3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnTScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdOJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ0snLCB0eXBlOiAndTMyJyB9LFxuICAgIF07XG4gICAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zKGFjdGl2YXRpb25BdHRyaWJ1dGVzLCB1bmlmb3Jtcyk7XG5cbiAgICBjb25zdCBjYWxjUmVzdWx0ID0gKCk6IHN0cmluZyA9PiB7XG4gICAgICBsZXQgY2FsY1N0ciA9IGB2YXIgYV9kYXRhOiAke2EudHlwZS52YWx1ZX07YDtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYUNvbXBvbmVudHM7IGkrKykge1xuICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICAgICAgbGV0IGJfZGF0YSR7aX0gPSBiWyhiX29mZnNldCArIChrICsgJHtpfSkgKiB1bmlmb3Jtcy5OICsgY29sKSAvICR7Y29tcG9uZW50c31dO2A7XG4gICAgICB9XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG91dHB1dE51bWJlcjsgaSsrKSB7XG4gICAgICAgIGNhbGNTdHIgKz0gYGFfZGF0YSA9IGFbKGFfb2Zmc2V0ICsgKHJvdyArICR7aX0pICogdW5pZm9ybXMuSyArIGspIC8gJHthQ29tcG9uZW50c31dO2A7XG5cbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBhQ29tcG9uZW50czsgaisrKSB7XG4gICAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgICB2YWx1ZXNbJHtpfV0gPSBmbWEoJHtiLnR5cGUudmFsdWV9KGFfZGF0YSR7YUNvbXBvbmVudHMgPT09IDEgPyAnJyA6IGBbJHtqfV1gfSksIGJfZGF0YSR7an0sIHZhbHVlc1ske2l9XSk7XFxuYDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGNhbGNTdHI7XG4gICAgfTtcblxuICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyXG4gICAgLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpXG4gICAgLnJlZ2lzdGVySW50ZXJuYWxWYXJpYWJsZXMoYmF0Y2hEaW1zKVxuICAgIC5kZWNsYXJlVmFyaWFibGVzKC4uLmlucHV0VmFyaWFibGVzLCBvdXRwdXQpfVxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuICAgIGxldCBjb2wgPSAoZ2xvYmFsX2lkeCAlICh1bmlmb3Jtcy5OIC8gJHtjb21wb25lbnRzfSkpICogJHtjb21wb25lbnRzfTtcbiAgICB2YXIgaW5kZXgxID0gZ2xvYmFsX2lkeCAvICh1bmlmb3Jtcy5OIC8gJHtjb21wb25lbnRzfSk7XG4gICAgbGV0IHN0cmlkZTEgPSB1bmlmb3Jtcy5NIC8gJHtvdXRwdXROdW1iZXJ9O1xuICAgIGxldCByb3cgPSAoaW5kZXgxICUgc3RyaWRlMSkgKiAke291dHB1dE51bWJlcn07XG4gICAgbGV0IGJhdGNoID0gaW5kZXgxIC8gc3RyaWRlMTtcblxuICAgICR7b3V0cHV0U2hhcGUubGVuZ3RoID09PSAyID8gJycgOiBgbGV0IGJhdGNoX2luZGljZXMgPSAke2JhdGNoRGltcy5vZmZzZXRUb0luZGljZXMoJ2JhdGNoJyl9O2B9XG5cbiAgICB2YXIgYV9pbmRpY2VzOiAke2EudHlwZS5pbmRpY2VzfTtcbiAgICAke2NvbnZlcnRPdXRwdXRCYXRjaEluZGljZXNUb0lucHV0QmF0Y2hJbmRpY2VzKCdhX2luZGljZXMnLCBhLCBhLnJhbmsgLSAyLCBiYXRjaERpbXMucmFuaywgJ2JhdGNoX2luZGljZXMnKX1cbiAgICAke2EuaW5kaWNlc1NldCgnYV9pbmRpY2VzJywgYS5yYW5rIC0gMiwgMCl9XG4gICAgJHthLmluZGljZXNTZXQoJ2FfaW5kaWNlcycsIGEucmFuayAtIDEsIDApfVxuICAgIGxldCBhX29mZnNldCA9ICR7YS5pbmRpY2VzVG9PZmZzZXQoJ2FfaW5kaWNlcycpfTtcblxuICAgIHZhciBiX2luZGljZXM6ICR7Yi50eXBlLmluZGljZXN9O1xuICAgICR7Y29udmVydE91dHB1dEJhdGNoSW5kaWNlc1RvSW5wdXRCYXRjaEluZGljZXMoJ2JfaW5kaWNlcycsIGIsIGIucmFuayAtIDIsIGJhdGNoRGltcy5yYW5rLCAnYmF0Y2hfaW5kaWNlcycpfVxuICAgICR7Yi5pbmRpY2VzU2V0KCdiX2luZGljZXMnLCBiLnJhbmsgLSAyLCAwKX1cbiAgICAke2IuaW5kaWNlc1NldCgnYl9pbmRpY2VzJywgYi5yYW5rIC0gMSwgMCl9XG4gICAgbGV0IGJfb2Zmc2V0ID0gJHtiLmluZGljZXNUb09mZnNldCgnYl9pbmRpY2VzJyl9O1xuICAgIHZhciB2YWx1ZXM6IGFycmF5PCR7b3V0cHV0LnR5cGUudmFsdWV9LCAke291dHB1dE51bWJlcn0+O1xuICAgIGZvciAodmFyIGs6IHUzMiA9IDB1OyBrIDwgdW5pZm9ybXMuSzsgayA9IGsgKyAke2FDb21wb25lbnRzfSkge1xuICAgICAgJHtjYWxjUmVzdWx0KCl9XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSAwdTsgaSA8ICR7b3V0cHV0TnVtYmVyfXU7IGkrKykge1xuICAgICAgdmFyIHZhbHVlID0gdmFsdWVzW2ldO1xuICAgICAgJHtwcm9jZXNzQmlhc31cbiAgICAgICR7YXBwbHlBY3RpdmF0aW9ufVxuICAgICAgbGV0IGN1cl9pbmRpY2VzID0gJHtvdXRwdXQudHlwZS5pbmRpY2VzfShiYXRjaCwgcm93ICsgaSwgY29sKTtcbiAgICAgIGxldCBvZmZzZXQgPSAke291dHB1dC5pbmRpY2VzVG9PZmZzZXQoJ2N1cl9pbmRpY2VzJyl9O1xuICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoYG9mZnNldCAvICR7Y29tcG9uZW50c31gLCAndmFsdWUnKX07XG4gICAgfVxuICB9XG4gIGA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ01hdE11bE5haXZlJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7YWN0aXZhdGlvbkF0dHJpYnV0ZXMuYWN0aXZhdGlvbn07JHtjb21wb25lbnRzfTske2FDb21wb25lbnRzfTske291dHB1dE51bWJlcn07JHtpc0NoYW5uZWxzTGFzdH1gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IGhhc0JpYXMgPyBbJ3JhbmsnLCAncmFuaycsICdyYW5rJ10gOiBbJ3JhbmsnLCAncmFuayddLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGRpbXM6IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uID8gc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24ob3V0cHV0U2hhcGUpIDogb3V0cHV0U2hhcGUsXG4gICAgICAgICAgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbi8vIHNhbXBsZWQgZnJvbSBbQHRlbnNvcmZsb3cvdGZqc10gdGZqcy1iYWNrZW5kLXdlYmdwdS9zcmMvbWF0bXVsX3BhY2tlZF93ZWJncHUudHNcbi8vXG4vLyBtb2RpZmllZCB0byBmaXQgdGhlIG5lZWRzIG9mIHRoZSBwcm9qZWN0XG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgUHJvZ3JhbUluZm8sIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uLy4uL3R5cGVzJztcbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBJbmRpY2VzSGVscGVyLFxuICBpbnB1dFZhcmlhYmxlLFxuICBpbnRlcm5hbFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuLi9jb21tb24nO1xuaW1wb3J0IHtcbiAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zLFxuICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXNEYXRhLFxuICBnZXRBY3RpdmF0aW9uU25pcHBldCxcbiAgSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyxcbn0gZnJvbSAnLi4vZnVzZS11dGlscyc7XG5pbXBvcnQgeyBjb252ZXJ0T3V0cHV0QmF0Y2hJbmRpY2VzVG9JbnB1dEJhdGNoSW5kaWNlcyB9IGZyb20gJy4uL21hdG11bC1zaGFkZXJzJztcblxuaW1wb3J0IHsgdHlwZVNuaXBwZXQgfSBmcm9tICcuL2FjdGl2YXRpb25fdXRpbCc7XG5cbmNvbnN0IHdyaXRlRGF0YVRvU3ViQVZlYzRTbmlwcGV0ID0gKHRyYW5zcG9zZTogYm9vbGVhbiwgYmF0Y2hEaW1zPzogSW5kaWNlc0hlbHBlcikgPT4ge1xuICBpZiAodHJhbnNwb3NlKSB7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgbW1fQXN1YltpbnB1dFJvd11baW5wdXRDb2xdID0gbW1fcmVhZEEoYmF0Y2gsXG4gICAgICAgICAga1N0YXJ0ICsgaW5wdXRSb3csXG4gICAgICAgICAgZ2xvYmFsUm93U3RhcnQgLyBpbm5lckVsZW1lbnRTaXplICsgaW5wdXRDb2wke2JhdGNoRGltcyA/ICcsIGJhdGNoSW5kaWNlcycgOiAnJ30pO1xuICAgICAgICBgO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBgXG4gICAgICAgIG1tX0FzdWJbaW5wdXRSb3ddW2lucHV0Q29sXSA9IG1tX3JlYWRBKGJhdGNoLFxuICAgICAgICAgIGdsb2JhbFJvdyArIGlubmVyUm93LFxuICAgICAgICAgIGtTdGFydCAvIGlubmVyRWxlbWVudFNpemUgKyBpbnB1dENvbCR7YmF0Y2hEaW1zID8gJywgYmF0Y2hJbmRpY2VzJyA6ICcnfSk7XG4gICAgICAgIGA7XG4gIH1cbn07XG5cbmNvbnN0IGNhbGN1bGF0ZVJlc3VsdFNuaXBwZXQgPSAodHJhbnNwb3NlQTogYm9vbGVhbiwgaW5uZXJFbGVtZW50U2l6ZTogbnVtYmVyKSA9PiB7XG4gIGlmICh0cmFuc3Bvc2VBKSB7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgbGV0IEFDYWNoZWQwID0gbW1fQXN1YltrICogaW5uZXJFbGVtZW50U2l6ZV1bbG9jYWxSb3ddO1xuICAgICAgICBsZXQgQUNhY2hlZDEgPSBtbV9Bc3ViW2sgKiBpbm5lckVsZW1lbnRTaXplICsgMV1bbG9jYWxSb3ddO1xuICAgICAgICBsZXQgQUNhY2hlZDIgPSBtbV9Bc3ViW2sgKiBpbm5lckVsZW1lbnRTaXplICsgMl1bbG9jYWxSb3ddO1xuICAgICAgICAke2lubmVyRWxlbWVudFNpemUgPT09IDMgPyAnJyA6ICdsZXQgQUNhY2hlZDMgPSBtbV9Bc3ViW2sgKiBpbm5lckVsZW1lbnRTaXplICsgM11bbG9jYWxSb3ddOyd9XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcm93UGVyVGhyZWFkOyBpID0gaSArIDEpIHtcbiAgICAgICAgICBhY2NbaV0gPSBCQ2FjaGVkMCAqIEFDYWNoZWQwW2ldICsgYWNjW2ldO1xuICAgICAgICAgIGFjY1tpXSA9IEJDYWNoZWQxICogQUNhY2hlZDFbaV0gKyBhY2NbaV07XG4gICAgICAgICAgYWNjW2ldID0gQkNhY2hlZDIgKiBBQ2FjaGVkMltpXSArIGFjY1tpXTtcbiAgICAgICAgICAke2lubmVyRWxlbWVudFNpemUgPT09IDMgPyAnJyA6ICdhY2NbaV0gPSBCQ2FjaGVkMyAqIEFDYWNoZWQzW2ldICsgYWNjW2ldOyd9XG4gICAgICAgIH1gO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBgXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcm93UGVyVGhyZWFkOyBpID0gaSArIDEpIHtcbiAgICAgICAgICBsZXQgQUNhY2hlZCA9IG1tX0FzdWJbdGlsZVJvdyArIGldW2tdO1xuICAgICAgICAgIGFjY1tpXSA9IEJDYWNoZWQwICogQUNhY2hlZC54ICsgYWNjW2ldO1xuICAgICAgICAgIGFjY1tpXSA9IEJDYWNoZWQxICogQUNhY2hlZC55ICsgYWNjW2ldO1xuICAgICAgICAgIGFjY1tpXSA9IEJDYWNoZWQyICogQUNhY2hlZC56ICsgYWNjW2ldO1xuICAgICAgICAgICR7aW5uZXJFbGVtZW50U2l6ZSA9PT0gMyA/ICcnIDogJ2FjY1tpXSA9IEJDYWNoZWQzICogQUNhY2hlZC53ICsgYWNjW2ldOyd9XG4gICAgICAgIH1gO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgbWFrZU1hdE11bFBhY2tlZFZlYzRTb3VyY2UgPSAoXG4gIHdvcmtQZXJUaHJlYWQ6IG51bWJlcltdLFxuICB3b3JrZ3JvdXBTaXplOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gIHR5cGUgPSAnZjMyJyxcbiAgYmF0Y2hEaW1zPzogSW5kaWNlc0hlbHBlcixcbiAgdHJhbnNwb3NlQSA9IGZhbHNlLFxuICB0aWxlSW5uZXIgPSAzMixcbiAgc3BsaXRLID0gZmFsc2UsXG4gIHNwbGl0ZWREaW1Jbm5lciA9IDMyLFxuKTogc3RyaW5nID0+IHtcbiAgY29uc3QgdGlsZUFPdXRlciA9IHdvcmtncm91cFNpemVbMV0gKiB3b3JrUGVyVGhyZWFkWzFdO1xuICBjb25zdCB0aWxlQk91dGVyID0gd29ya2dyb3VwU2l6ZVswXSAqIHdvcmtQZXJUaHJlYWRbMF07XG4gIGNvbnN0IHRpbGVBV2lkdGggPSB0cmFuc3Bvc2VBID8gdGlsZUFPdXRlciA6IHRpbGVJbm5lcjtcbiAgY29uc3QgdGlsZUFIaWdodCA9IHRyYW5zcG9zZUEgPyB0aWxlSW5uZXIgOiB0aWxlQU91dGVyO1xuICBjb25zdCBpbm5lckVsZW1lbnRTaXplID0gdGlsZUFXaWR0aCAvIHdvcmtncm91cFNpemVbMF07XG4gIGNvbnN0IHJvd1BlclRocmVhZEIgPSB0aWxlSW5uZXIgLyB3b3JrZ3JvdXBTaXplWzFdO1xuXG4gIGlmIChcbiAgICAhKFxuICAgICAgKCh0cmFuc3Bvc2VBICYmIGlubmVyRWxlbWVudFNpemUgPT09IDQgJiYgd29ya1BlclRocmVhZFsxXSA9PT0gNCkgfHxcbiAgICAgICAgKCF0cmFuc3Bvc2VBICYmIChpbm5lckVsZW1lbnRTaXplID09PSAzIHx8IGlubmVyRWxlbWVudFNpemUgPT09IDQpKSkgJiZcbiAgICAgIHRpbGVBV2lkdGggJSB3b3JrZ3JvdXBTaXplWzBdID09PSAwICYmXG4gICAgICB0aWxlSW5uZXIgJSB3b3JrZ3JvdXBTaXplWzFdID09PSAwICYmXG4gICAgICB3b3JrUGVyVGhyZWFkWzBdID09PSA0XG4gICAgKVxuICApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYElmIHRyYW5zcG9zZUEgJHt0cmFuc3Bvc2VBfSBpcyB0cnVlLCBpbm5lckVsZW1lbnRTaXplICR7aW5uZXJFbGVtZW50U2l6ZX0gYW5kIHdvcmtQZXJUaHJlYWRbMV0gJHt3b3JrUGVyVGhyZWFkWzFdfSBtdXN0IGJlIDQuXG4gICAgICBPdGhlcndpc2UsIGlubmVyRWxlbWVudFNpemUgJHtpbm5lckVsZW1lbnRTaXplfSBtdXN0IGJlIDMgb3IgNC5cbiAgdGlsZUFXaWR0aCAke3RpbGVBV2lkdGh9IG11c3QgYmUgZGl2aXNpYmxlIGJ5IHdvcmtncm91cFNpemVbMF0ke3dvcmtncm91cFNpemVbMF19LiB0aWxlSW5uZXIgJHt0aWxlSW5uZXJ9IG11c3QgYmUgZGl2aXNpYmxlIGJ5IHdvcmtncm91cFNpemVbMV0gJHt3b3JrZ3JvdXBTaXplWzFdfS4gY29sUGVyVGhyZWFkICR7d29ya1BlclRocmVhZFswXX0gbXVzdCBiZSA0LmApO1xuICB9XG4gIHJldHVybiBgXG52YXI8d29ya2dyb3VwPiBtbV9Bc3ViOiBhcnJheTxhcnJheTx2ZWMke2lubmVyRWxlbWVudFNpemV9PCR7dHlwZX0+LCAke3RpbGVBV2lkdGggLyBpbm5lckVsZW1lbnRTaXplfT4sICR7dGlsZUFIaWdodH0+O1xudmFyPHdvcmtncm91cD4gbW1fQnN1YjogYXJyYXk8YXJyYXk8dmVjNDwke3R5cGV9PiwgJHt0aWxlQk91dGVyIC8gd29ya1BlclRocmVhZFswXX0+LCAke3RpbGVJbm5lcn0+O1xuXG5jb25zdCByb3dQZXJUaHJlYWQgPSAke3dvcmtQZXJUaHJlYWRbMV19O1xuY29uc3QgY29sUGVyVGhyZWFkID0gJHt3b3JrUGVyVGhyZWFkWzBdfTtcbmNvbnN0IGlubmVyRWxlbWVudFNpemUgPSAke2lubmVyRWxlbWVudFNpemV9O1xuY29uc3QgdGlsZUlubmVyID0gJHt0aWxlSW5uZXJ9O1xuXG5AY29tcHV0ZSBAd29ya2dyb3VwX3NpemUoJHt3b3JrZ3JvdXBTaXplWzBdfSwgJHt3b3JrZ3JvdXBTaXplWzFdfSwgJHt3b3JrZ3JvdXBTaXplWzJdfSlcbmZuIG1haW4oQGJ1aWx0aW4obG9jYWxfaW52b2NhdGlvbl9pZCkgbG9jYWxJZCA6IHZlYzM8dTMyPixcbiAgICAgICAgQGJ1aWx0aW4oZ2xvYmFsX2ludm9jYXRpb25faWQpIGdsb2JhbElkIDogdmVjMzx1MzI+LFxuICAgICAgICBAYnVpbHRpbih3b3JrZ3JvdXBfaWQpIHdvcmtncm91cElkIDogdmVjMzx1MzI+KSB7XG4gIGxldCBsb2NhbFJvdyA9IGkzMihsb2NhbElkLnkpO1xuICBsZXQgdGlsZVJvdyA9IGxvY2FsUm93ICogcm93UGVyVGhyZWFkO1xuICBsZXQgdGlsZUNvbCA9IGkzMihsb2NhbElkLngpO1xuXG4gIGxldCBnbG9iYWxSb3cgPWkzMihnbG9iYWxJZC55KSAqIHJvd1BlclRocmVhZDtcbiAgbGV0IGdsb2JhbENvbCA9IGkzMihnbG9iYWxJZC54KTtcbiAgbGV0IGJhdGNoID0gJHtzcGxpdEsgPyAnMCcgOiAnaTMyKGdsb2JhbElkLnopJ307XG4gICR7YmF0Y2hEaW1zID8gYGxldCBiYXRjaEluZGljZXMgPSAke2JhdGNoRGltcy5vZmZzZXRUb0luZGljZXMoJ3UzMihiYXRjaCknKX07YCA6ICcnfVxuICBsZXQgZ2xvYmFsUm93U3RhcnQgPSBpMzIod29ya2dyb3VwSWQueSkgKiAke3RpbGVBT3V0ZXJ9O1xuXG4gIGxldCBudW1fdGlsZXMgPSAke3NwbGl0SyA/IGAke01hdGguY2VpbChzcGxpdGVkRGltSW5uZXIgLyB0aWxlSW5uZXIpfWAgOiAnKHVuaWZvcm1zLmRpbV9pbm5lciAtIDEpIC8gdGlsZUlubmVyICsgMSd9O1xuICB2YXIga1N0YXJ0ID0gJHtzcGxpdEsgPyBgaTMyKGdsb2JhbElkLnopICogJHtzcGxpdGVkRGltSW5uZXJ9YCA6ICcwJ307XG5cbiAgdmFyIGFjYzogYXJyYXk8dmVjNDwke3R5cGV9Piwgcm93UGVyVGhyZWFkPjtcblxuICAvLyBMb29wIG92ZXIgc2hhcmVkIGRpbWVuc2lvbi5cbiAgbGV0IHRpbGVSb3dCID0gbG9jYWxSb3cgKiAke3Jvd1BlclRocmVhZEJ9O1xuICBmb3IgKHZhciB0ID0gMDsgdCA8IG51bV90aWxlczsgdCA9IHQgKyAxKSB7XG4gICAgICAvLyBMb2FkIG9uZSB0aWxlIG9mIEEgaW50byBsb2NhbCBtZW1vcnkuXG4gICAgICBmb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgcm93UGVyVGhyZWFkOyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgICAgICAgIGxldCBpbnB1dFJvdyA9IHRpbGVSb3cgKyBpbm5lclJvdztcbiAgICAgICAgICBsZXQgaW5wdXRDb2wgPSB0aWxlQ29sO1xuICAgICAgICAgICR7d3JpdGVEYXRhVG9TdWJBVmVjNFNuaXBwZXQodHJhbnNwb3NlQSwgYmF0Y2hEaW1zKX1cbiAgICAgIH1cblxuICAgICAgLy8gTG9hZCBvbmUgdGlsZSBvZiBCIGludG8gbG9jYWwgbWVtb3J5LlxuICAgICAgZm9yICh2YXIgaW5uZXJSb3cgPSAwOyBpbm5lclJvdyA8ICR7cm93UGVyVGhyZWFkQn07IGlubmVyUm93ID0gaW5uZXJSb3cgKyAxKSB7XG4gICAgICAgICAgbGV0IGlucHV0Um93ID0gdGlsZVJvd0IgKyBpbm5lclJvdztcbiAgICAgICAgICBsZXQgaW5wdXRDb2wgPSB0aWxlQ29sO1xuICAgICAgICAgIG1tX0JzdWJbaW5wdXRSb3ddW2lucHV0Q29sXSA9IG1tX3JlYWRCKGJhdGNoLCBrU3RhcnQgKyBpbnB1dFJvdywgZ2xvYmFsQ29sJHtcbiAgICAgICAgICAgIGJhdGNoRGltcyA/ICcsIGJhdGNoSW5kaWNlcycgOiAnJ1xuICAgICAgICAgIH0pO1xuICAgICAgfVxuICAgICAga1N0YXJ0ID0ga1N0YXJ0ICsgdGlsZUlubmVyO1xuICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuXG4gICAgICAvLyBDb21wdXRlIGFjYyB2YWx1ZXMgZm9yIGEgc2luZ2xlIHRocmVhZC5cbiAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgdGlsZUlubmVyIC8gaW5uZXJFbGVtZW50U2l6ZTsgayA9IGsgKyAxKSB7XG4gICAgICAgICAgbGV0IEJDYWNoZWQwID0gbW1fQnN1YltrICogaW5uZXJFbGVtZW50U2l6ZV1bdGlsZUNvbF07XG4gICAgICAgICAgbGV0IEJDYWNoZWQxID0gbW1fQnN1YltrICogaW5uZXJFbGVtZW50U2l6ZSArIDFdW3RpbGVDb2xdO1xuICAgICAgICAgIGxldCBCQ2FjaGVkMiA9IG1tX0JzdWJbayAqIGlubmVyRWxlbWVudFNpemUgKyAyXVt0aWxlQ29sXTtcbiAgICAgICAgICAke2lubmVyRWxlbWVudFNpemUgPT09IDMgPyAnJyA6ICdsZXQgQkNhY2hlZDMgPSBtbV9Cc3ViW2sgKiBpbm5lckVsZW1lbnRTaXplICsgM11bdGlsZUNvbF07J31cblxuICAgICAgICAgICR7Y2FsY3VsYXRlUmVzdWx0U25pcHBldCh0cmFuc3Bvc2VBLCBpbm5lckVsZW1lbnRTaXplKX1cbiAgICAgIH1cblxuICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuICB9XG5cbiAgZm9yICh2YXIgaW5uZXJSb3cgPSAwOyBpbm5lclJvdyA8IHJvd1BlclRocmVhZDsgaW5uZXJSb3cgPSBpbm5lclJvdyArIDEpIHtcbiAgICAgIG1tX3dyaXRlKGJhdGNoLCBnbG9iYWxSb3cgKyBpbm5lclJvdywgZ2xvYmFsQ29sLCBhY2NbaW5uZXJSb3ddKTtcbiAgfVxufWA7XG59O1xuXG5jb25zdCB3cml0ZURhdGFUb1N1YkFTbmlwcGV0ID0gKHRyYW5zcG9zZTogYm9vbGVhbiwgYmF0Y2hEaW1zPzogSW5kaWNlc0hlbHBlcikgPT4ge1xuICBpZiAodHJhbnNwb3NlKSB7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgICAgIG1tX0FzdWJbaW5wdXRSb3ddW2lucHV0Q29sXSA9IG1tX3JlYWRBKGJhdGNoLFxuICAgICAgICAgICAgICBrU3RhcnQgKyBpbnB1dFJvdyxcbiAgICAgICAgICAgICAgZ2xvYmFsUm93U3RhcnQgKyBpbnB1dENvbCR7YmF0Y2hEaW1zID8gJywgYmF0Y2hJbmRpY2VzJyA6ICcnfSk7XG4gICAgICAgICAgICBgO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBgXG4gICAgICAgICAgICBtbV9Bc3ViW2lucHV0Um93XVtpbnB1dENvbF0gPSBtbV9yZWFkQShiYXRjaCxcbiAgICAgICAgICAgICAgZ2xvYmFsUm93U3RhcnQgKyBpbnB1dFJvdyxcbiAgICAgICAgICAgICAga1N0YXJ0ICsgaW5wdXRDb2wke2JhdGNoRGltcyA/ICcsIGJhdGNoSW5kaWNlcycgOiAnJ30pO1xuICAgICAgICAgICAgYDtcbiAgfVxufTtcblxuY29uc3QgcmVhZERhdGFGcm9tU3ViQVNuaXBwZXQgPSAodHJhbnNwb3NlQTogYm9vbGVhbikgPT5cbiAgdHJhbnNwb3NlQSA/ICdsZXQgQUNhY2hlZCA9IG1tX0FzdWJba11bdGlsZVJvdyArIGlubmVyUm93XTsnIDogJ2xldCBBQ2FjaGVkID0gbW1fQXN1Ylt0aWxlUm93ICsgaW5uZXJSb3ddW2tdOyc7XG5cbi8vIHNlcXVlbnRpYWxBY2Nlc3NCeVRocmVhZHMgbWVhbnMgc2VxdWVudGlhbCBkYXRhIGluIG1lbW9yeSBpcyBhY2Nlc3NlZCBieVxuLy8gdGhyZWFkcywgaW5zdGVhZCBvZiBhIHNpbmdsZSB0aHJlYWQgKGRlZmF1bHQgYmVoYXZpb3IpLlxuZXhwb3J0IGNvbnN0IG1ha2VNYXRNdWxQYWNrZWRTb3VyY2UgPSAoXG4gIHdvcmtQZXJUaHJlYWQ6IG51bWJlcltdLFxuICB3b3JrZ3JvdXBTaXplOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gIHR5cGUgPSAnZjMyJyxcbiAgYmF0Y2hEaW1zPzogSW5kaWNlc0hlbHBlcixcbiAgdHJhbnNwb3NlQSA9IGZhbHNlLFxuICB0aWxlSW5uZXIgPSAzMixcbiAgc3BsaXRLID0gZmFsc2UsXG4gIHNwbGl0ZWREaW1Jbm5lciA9IDMyLFxuICBzZXF1ZW50aWFsQWNjZXNzQnlUaHJlYWRzID0gZmFsc2UsXG4pOiBzdHJpbmcgPT4ge1xuICBjb25zdCB0aWxlQU91dGVyID0gd29ya1BlclRocmVhZFsxXSAqIHdvcmtncm91cFNpemVbMV07XG4gIGNvbnN0IHRpbGVCT3V0ZXIgPSB3b3JrUGVyVGhyZWFkWzBdICogd29ya2dyb3VwU2l6ZVswXTtcbiAgY29uc3QgdGlsZUFXaWR0aCA9IHRyYW5zcG9zZUEgPyB0aWxlQU91dGVyIDogdGlsZUlubmVyO1xuICBjb25zdCB0aWxlQUhpZ2h0ID0gdHJhbnNwb3NlQSA/IHRpbGVJbm5lciA6IHRpbGVBT3V0ZXI7XG5cbiAgaWYgKFxuICAgICEodGlsZUFIaWdodCAlIHdvcmtncm91cFNpemVbMV0gPT09IDAgJiYgdGlsZUFXaWR0aCAlIHdvcmtncm91cFNpemVbMF0gPT09IDAgJiYgdGlsZUlubmVyICUgd29ya2dyb3VwU2l6ZVsxXSA9PT0gMClcbiAgKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYHRpbGVBSGlnaHQgJHt0aWxlQUhpZ2h0fSBtdXN0IGJlIGRpdmlzaWJsZSBieSB3b3JrZ3JvdXBTaXplWzFdJHt3b3JrZ3JvdXBTaXplWzFdfSwgdGlsZUFXaWR0aCAke3RpbGVBV2lkdGh9IG11c3QgYmUgZGl2aXNpYmxlIGJ5IHdvcmtncm91cFNpemVbMF0ke3dvcmtncm91cFNpemVbMF19LCB0aWxlSW5uZXIgJHt0aWxlSW5uZXJ9IG11c3QgYmUgZGl2aXNpYmxlIGJ5IHdvcmtncm91cFNpemVbMV0ke3dvcmtncm91cFNpemVbMV19YCxcbiAgICApO1xuICB9XG4gIGNvbnN0IHJvd1BlclRocmVhZEEgPSB0aWxlQUhpZ2h0IC8gd29ya2dyb3VwU2l6ZVsxXTtcbiAgY29uc3QgY29sUGVyVGhyZWFkQSA9IHRpbGVBV2lkdGggLyB3b3JrZ3JvdXBTaXplWzBdO1xuICBjb25zdCByb3dQZXJUaHJlYWRCID0gdGlsZUlubmVyIC8gd29ya2dyb3VwU2l6ZVsxXTtcbiAgY29uc3QgbWF0bXVsU25pcHBldCA9IHNlcXVlbnRpYWxBY2Nlc3NCeVRocmVhZHNcbiAgICA/IGBcbiAgICBsZXQgbG9jYWxSb3cgPSBpMzIobG9jYWxJZC55KTtcbiAgICBsZXQgbG9jYWxDb2wgPSBpMzIobG9jYWxJZC54KTtcbiAgICBsZXQgZ2xvYmFsUm93U3RhcnQgPSBpMzIod29ya2dyb3VwSWQueSkgKiAke3RpbGVBT3V0ZXJ9O1xuICAgIGxldCBnbG9iYWxDb2xTdGFydCA9IGkzMih3b3JrZ3JvdXBJZC54KSAqICR7dGlsZUJPdXRlcn07XG5cbiAgICAvLyBMb29wIG92ZXIgc2hhcmVkIGRpbWVuc2lvbi5cbiAgICBmb3IgKHZhciB0ID0gMDsgdCA8IG51bV90aWxlczsgdCA9IHQgKyAxKSB7XG4gICAgICAvLyBMb2FkIG9uZSB0aWxlIG9mIEEgaW50byBsb2NhbCBtZW1vcnkuXG4gICAgICBmb3IgKHZhciBpbnB1dFJvdyA9IGxvY2FsUm93OyBpbnB1dFJvdyA8ICR7dGlsZUFIaWdodH07IGlucHV0Um93ID0gaW5wdXRSb3cgKyAke3dvcmtncm91cFNpemVbMV19KSB7XG4gICAgICAgIGZvciAodmFyIGlucHV0Q29sID0gbG9jYWxDb2w7IGlucHV0Q29sIDwgJHt0aWxlQVdpZHRofTsgaW5wdXRDb2wgPSBpbnB1dENvbCArICR7d29ya2dyb3VwU2l6ZVswXX0pIHtcbiAgICAgICAgICAke3dyaXRlRGF0YVRvU3ViQVNuaXBwZXQodHJhbnNwb3NlQSwgYmF0Y2hEaW1zKX1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gTG9hZCBvbmUgdGlsZSBvZiBCIGludG8gbG9jYWwgbWVtb3J5LlxuICAgICAgZm9yICh2YXIgaW5wdXRSb3cgPSBsb2NhbFJvdzsgaW5wdXRSb3cgPCAke3RpbGVJbm5lcn07IGlucHV0Um93ID0gaW5wdXRSb3cgKyAke3dvcmtncm91cFNpemVbMV19KSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpbnB1dENvbCA9IGxvY2FsQ29sOyBpbnB1dENvbCA8ICR7dGlsZUJPdXRlcn07IGlucHV0Q29sID0gaW5wdXRDb2wgKyAke3dvcmtncm91cFNpemVbMF19KSB7XG4gICAgICAgICAgbW1fQnN1YltpbnB1dFJvd11baW5wdXRDb2xdID0gbW1fcmVhZEIoYmF0Y2gsXG4gICAgICAgICAgICBrU3RhcnQgKyBpbnB1dFJvdyxcbiAgICAgICAgICAgIGdsb2JhbENvbFN0YXJ0ICsgaW5wdXRDb2wke2JhdGNoRGltcyA/ICcsIGJhdGNoSW5kaWNlcycgOiAnJ30pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBrU3RhcnQgPSBrU3RhcnQgKyB0aWxlSW5uZXI7XG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgIC8vIENvbXB1dGUgYWNjIHZhbHVlcyBmb3IgYSBzaW5nbGUgdGhyZWFkLlxuICAgICAgdmFyIEJDYWNoZWQgOiBhcnJheTwke3R5cGV9LCBjb2xQZXJUaHJlYWQ+O1xuICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aWxlSW5uZXI7IGsgPSBrICsgMSkge1xuICAgICAgICBmb3IgKHZhciBpbm5lciA9IDA7IGlubmVyIDwgY29sUGVyVGhyZWFkOyBpbm5lciA9IGlubmVyICsgMSkge1xuICAgICAgICAgIEJDYWNoZWRbaW5uZXJdID0gbW1fQnN1YltrXVtsb2NhbENvbCArIGlubmVyICogJHt3b3JrZ3JvdXBTaXplWzBdfV07XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgaW5uZXJSb3cgPSAwOyBpbm5lclJvdyA8IHJvd1BlclRocmVhZDsgaW5uZXJSb3cgPSBpbm5lclJvdyArIDEpIHtcbiAgICAgICAgICBsZXQgQUNhY2hlZCA9ICR7XG4gICAgICAgICAgICB0cmFuc3Bvc2VBXG4gICAgICAgICAgICAgID8gYG1tX0FzdWJba11bbG9jYWxSb3cgKyBpbm5lclJvdyAqICR7d29ya2dyb3VwU2l6ZVsxXX1dO2BcbiAgICAgICAgICAgICAgOiBgbW1fQXN1Yltsb2NhbFJvdyArIGlubmVyUm93ICogJHt3b3JrZ3JvdXBTaXplWzFdfV1ba107YFxuICAgICAgICAgIH1cbiAgICAgICAgICBmb3IgKHZhciBpbm5lckNvbCA9IDA7IGlubmVyQ29sIDwgY29sUGVyVGhyZWFkOyBpbm5lckNvbCA9IGlubmVyQ29sICsgMSkge1xuICAgICAgICAgICAgYWNjW2lubmVyUm93XVtpbm5lckNvbF0gPSBhY2NbaW5uZXJSb3ddW2lubmVyQ29sXSArXG4gICAgICAgICAgICAgICAgQUNhY2hlZCAqIEJDYWNoZWRbaW5uZXJDb2xdO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuICAgIH1cbiAgICBmb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgcm93UGVyVGhyZWFkOyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgICAgbGV0IGdSb3cgPSBnbG9iYWxSb3dTdGFydCArIGxvY2FsUm93ICsgaW5uZXJSb3cgKiAke3dvcmtncm91cFNpemVbMV19O1xuICAgICAgZm9yICh2YXIgaW5uZXJDb2wgPSAwOyBpbm5lckNvbCA8IGNvbFBlclRocmVhZDsgaW5uZXJDb2wgPSBpbm5lckNvbCArIDEpIHtcbiAgICAgICAgbGV0IGdDb2wgPSBnbG9iYWxDb2xTdGFydCArIGxvY2FsQ29sICsgaW5uZXJDb2wgKiAke3dvcmtncm91cFNpemVbMF19O1xuICAgICAgICBtbV93cml0ZShiYXRjaCwgZ1JvdywgZ0NvbCwgYWNjW2lubmVyUm93XVtpbm5lckNvbF0pO1xuICAgICAgfVxuICAgIH1cbiAgICBgXG4gICAgOiBgXG5sZXQgdGlsZVJvdyA9IGkzMihsb2NhbElkLnkpICogcm93UGVyVGhyZWFkO1xubGV0IHRpbGVDb2wgPSBpMzIobG9jYWxJZC54KSAqIGNvbFBlclRocmVhZDtcblxubGV0IGdsb2JhbFJvdyA9IGkzMihnbG9iYWxJZC55KSAqIHJvd1BlclRocmVhZDtcbmxldCBnbG9iYWxDb2wgPSBpMzIoZ2xvYmFsSWQueCkgKiBjb2xQZXJUaHJlYWQ7XG5sZXQgZ2xvYmFsUm93U3RhcnQgPSBpMzIod29ya2dyb3VwSWQueSkgKiAke3RpbGVBT3V0ZXJ9O1xuXG5sZXQgdGlsZVJvd0EgPSBpMzIobG9jYWxJZC55KSAqICR7cm93UGVyVGhyZWFkQX07XG5sZXQgdGlsZUNvbEEgPSBpMzIobG9jYWxJZC54KSAqICR7Y29sUGVyVGhyZWFkQX07XG5sZXQgdGlsZVJvd0IgPSBpMzIobG9jYWxJZC55KSAqICR7cm93UGVyVGhyZWFkQn07XG4vLyBMb29wIG92ZXIgc2hhcmVkIGRpbWVuc2lvbi5cbmZvciAodmFyIHQgPSAwOyB0IDwgbnVtX3RpbGVzOyB0ID0gdCArIDEpIHtcbiAgLy8gTG9hZCBvbmUgdGlsZSBvZiBBIGludG8gbG9jYWwgbWVtb3J5LlxuICBmb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgJHtyb3dQZXJUaHJlYWRBfTsgaW5uZXJSb3cgPSBpbm5lclJvdyArIDEpIHtcbiAgICBmb3IgKHZhciBpbm5lckNvbCA9IDA7IGlubmVyQ29sIDwgJHtjb2xQZXJUaHJlYWRBfTsgaW5uZXJDb2wgPSBpbm5lckNvbCArIDEpIHtcbiAgICAgIGxldCBpbnB1dFJvdyA9IHRpbGVSb3dBICsgaW5uZXJSb3c7XG4gICAgICBsZXQgaW5wdXRDb2wgPSB0aWxlQ29sQSArIGlubmVyQ29sO1xuICAgICAgJHt3cml0ZURhdGFUb1N1YkFTbmlwcGV0KHRyYW5zcG9zZUEsIGJhdGNoRGltcyl9XG4gICAgfVxuICB9XG5cbiAgLy8gTG9hZCBvbmUgdGlsZSBvZiBCIGludG8gbG9jYWwgbWVtb3J5LlxuICBmb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgJHtyb3dQZXJUaHJlYWRCfTsgaW5uZXJSb3cgPSBpbm5lclJvdyArIDEpIHtcbiAgICBmb3IgKHZhciBpbm5lckNvbCA9IDA7IGlubmVyQ29sIDwgY29sUGVyVGhyZWFkOyBpbm5lckNvbCA9IGlubmVyQ29sICsgMSkge1xuICAgICAgbGV0IGlucHV0Um93ID0gdGlsZVJvd0IgKyBpbm5lclJvdztcbiAgICAgIGxldCBpbnB1dENvbCA9IHRpbGVDb2wgKyBpbm5lckNvbDtcbiAgICAgIG1tX0JzdWJbaW5wdXRSb3ddW2lucHV0Q29sXSA9IG1tX3JlYWRCKGJhdGNoLFxuICAgICAgICBrU3RhcnQgKyBpbnB1dFJvdyxcbiAgICAgICAgZ2xvYmFsQ29sICsgaW5uZXJDb2wke2JhdGNoRGltcyA/ICcsIGJhdGNoSW5kaWNlcycgOiAnJ30pO1xuICAgIH1cbiAgfVxuICBrU3RhcnQgPSBrU3RhcnQgKyB0aWxlSW5uZXI7XG4gIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAvLyBDb21wdXRlIGFjYyB2YWx1ZXMgZm9yIGEgc2luZ2xlIHRocmVhZC5cbiAgdmFyIEJDYWNoZWQgOiBhcnJheTwke3R5cGV9LCBjb2xQZXJUaHJlYWQ+O1xuICBmb3IgKHZhciBrID0gMDsgayA8IHRpbGVJbm5lcjsgayA9IGsgKyAxKSB7XG4gICAgZm9yICh2YXIgaW5uZXIgPSAwOyBpbm5lciA8IGNvbFBlclRocmVhZDsgaW5uZXIgPSBpbm5lciArIDEpIHtcbiAgICAgIEJDYWNoZWRbaW5uZXJdID0gbW1fQnN1YltrXVt0aWxlQ29sICsgaW5uZXJdO1xuICAgIH1cblxuICAgIGZvciAodmFyIGlubmVyUm93ID0gMDsgaW5uZXJSb3cgPCByb3dQZXJUaHJlYWQ7IGlubmVyUm93ID0gaW5uZXJSb3cgKyAxKSB7XG4gICAgICAke3JlYWREYXRhRnJvbVN1YkFTbmlwcGV0KHRyYW5zcG9zZUEpfVxuICAgICAgZm9yICh2YXIgaW5uZXJDb2wgPSAwOyBpbm5lckNvbCA8IGNvbFBlclRocmVhZDsgaW5uZXJDb2wgPSBpbm5lckNvbCArIDEpIHtcbiAgICAgICAgYWNjW2lubmVyUm93XVtpbm5lckNvbF0gPSBhY2NbaW5uZXJSb3ddW2lubmVyQ29sXSArIEFDYWNoZWQgKiBCQ2FjaGVkW2lubmVyQ29sXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG59XG5cbmZvciAodmFyIGlubmVyUm93ID0gMDsgaW5uZXJSb3cgPCByb3dQZXJUaHJlYWQ7IGlubmVyUm93ID0gaW5uZXJSb3cgKyAxKSB7XG4gIGZvciAodmFyIGlubmVyQ29sID0gMDsgaW5uZXJDb2wgPCBjb2xQZXJUaHJlYWQ7IGlubmVyQ29sID0gaW5uZXJDb2wgKyAxKSB7XG4gICAgbW1fd3JpdGUoYmF0Y2gsIGdsb2JhbFJvdyArIGlubmVyUm93LCBnbG9iYWxDb2wgKyBpbm5lckNvbCxcbiAgICAgICAgYWNjW2lubmVyUm93XVtpbm5lckNvbF0pO1xuICB9XG59XG5gO1xuXG4gIHJldHVybiBgXG4gIHZhcjx3b3JrZ3JvdXA+IG1tX0FzdWIgOiBhcnJheTxhcnJheTwke3R5cGV9LCAke3RpbGVBV2lkdGh9PiwgJHt0aWxlQUhpZ2h0fT47XG4gIHZhcjx3b3JrZ3JvdXA+IG1tX0JzdWIgOiBhcnJheTxhcnJheTwke3R5cGV9LCAke3RpbGVCT3V0ZXJ9PiwgJHt0aWxlSW5uZXJ9PjtcbiAgY29uc3Qgcm93UGVyVGhyZWFkID0gJHt3b3JrUGVyVGhyZWFkWzFdfTtcbiAgY29uc3QgY29sUGVyVGhyZWFkID0gJHt3b3JrUGVyVGhyZWFkWzBdfTtcbiAgY29uc3QgdGlsZUlubmVyID0gJHt0aWxlSW5uZXJ9O1xuXG5AY29tcHV0ZSBAd29ya2dyb3VwX3NpemUoJHt3b3JrZ3JvdXBTaXplWzBdfSwgJHt3b3JrZ3JvdXBTaXplWzFdfSwgJHt3b3JrZ3JvdXBTaXplWzJdfSlcbmZuIG1haW4oQGJ1aWx0aW4obG9jYWxfaW52b2NhdGlvbl9pZCkgbG9jYWxJZCA6IHZlYzM8dTMyPixcbiAgICAgICAgQGJ1aWx0aW4oZ2xvYmFsX2ludm9jYXRpb25faWQpIGdsb2JhbElkIDogdmVjMzx1MzI+LFxuICAgICAgICBAYnVpbHRpbih3b3JrZ3JvdXBfaWQpIHdvcmtncm91cElkIDogdmVjMzx1MzI+KSB7XG4gICAgbGV0IGJhdGNoID0gJHtzcGxpdEsgPyAnMCcgOiAnaTMyKGdsb2JhbElkLnopJ307XG4gICAgJHtiYXRjaERpbXMgPyBgbGV0IGJhdGNoSW5kaWNlcyA9ICR7YmF0Y2hEaW1zLm9mZnNldFRvSW5kaWNlcygndTMyKGJhdGNoKScpfTtgIDogJyd9XG4gICAgbGV0IG51bV90aWxlcyA9ICR7XG4gICAgICBzcGxpdEsgPyBgJHtNYXRoLmNlaWwoc3BsaXRlZERpbUlubmVyIC8gdGlsZUlubmVyKX1gIDogJyh1bmlmb3Jtcy5kaW1faW5uZXIgLSAxKSAvIHRpbGVJbm5lciArIDEnXG4gICAgfTtcbiAgICB2YXIga1N0YXJ0ID0gJHtzcGxpdEsgPyBgaTMyKGdsb2JhbElkLnopICogJHtzcGxpdGVkRGltSW5uZXJ9YCA6ICcwJ307XG5cbiAgICB2YXIgYWNjIDogYXJyYXk8YXJyYXk8JHt0eXBlfSwgY29sUGVyVGhyZWFkPiwgcm93UGVyVGhyZWFkPjtcbiAgICAke21hdG11bFNuaXBwZXR9XG4gIH1cbmA7XG59O1xuXG5jb25zdCBtYXRNdWxSZWFkV3JpdGVGblNvdXJjZSA9IChcbiAgY29tcG9uZW50OiBudW1iZXIsXG4gIGhhc0JpYXM6IGJvb2xlYW4sXG4gIGFwcGx5QWN0aXZhdGlvbjogc3RyaW5nLFxuICB2YXJpYWJsZXM6IEluZGljZXNIZWxwZXJbXSxcbiAgaXNDaGFubmVsc0xhc3QgPSBmYWxzZSxcbik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IFtiYXRjaFZhcmlhYmxlLCBhVmFyaWFibGUsIGJWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGVdID0gdmFyaWFibGVzO1xuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSh2YXJpYWJsZXNbMF0udHlwZS50ZW5zb3IpO1xuXG4gIGNvbnN0IHNvdXJjZSA9IGBcbiAgICBmbiBtbV9yZWFkQShiYXRjaDogaTMyLCByb3c6IGkzMiwgY29sSW46IGkzMiwgYmF0Y2hJbmRpY2VzOiAke2JhdGNoVmFyaWFibGUudHlwZS5pbmRpY2VzfSkgLT4gJHt0eXBlU25pcHBldChcbiAgICAgIGNvbXBvbmVudCxcbiAgICAgIGRhdGFUeXBlLFxuICAgICl9IHtcbiAgICAgIHZhciB2YWx1ZSA9ICR7dHlwZVNuaXBwZXQoY29tcG9uZW50LCBkYXRhVHlwZSl9KDAuMCk7XG4gICAgICBsZXQgY29sID0gY29sSW4gKiAke2NvbXBvbmVudH07XG4gICAgICBpZihyb3cgPCB1bmlmb3Jtcy5kaW1fYV9vdXRlciAmJiBjb2wgPCB1bmlmb3Jtcy5kaW1faW5uZXIpXG4gICAgICB7XG4gICAgICAgIHZhciBhSW5kaWNlczogJHthVmFyaWFibGUudHlwZS5pbmRpY2VzfTtcbiAgICAgICAgJHtjb252ZXJ0T3V0cHV0QmF0Y2hJbmRpY2VzVG9JbnB1dEJhdGNoSW5kaWNlcyhcbiAgICAgICAgICAnYUluZGljZXMnLFxuICAgICAgICAgIGFWYXJpYWJsZSxcbiAgICAgICAgICBhVmFyaWFibGUucmFuayAtIDIsXG4gICAgICAgICAgYmF0Y2hWYXJpYWJsZS5yYW5rLFxuICAgICAgICAgICdiYXRjaEluZGljZXMnLFxuICAgICAgICApfVxuICAgICAgICAke2FWYXJpYWJsZS5pbmRpY2VzU2V0KCdhSW5kaWNlcycsIGFWYXJpYWJsZS5yYW5rIC0gMiwgJ3UzMihyb3cpJyl9XG4gICAgICAgICR7YVZhcmlhYmxlLmluZGljZXNTZXQoJ2FJbmRpY2VzJywgYVZhcmlhYmxlLnJhbmsgLSAxLCAndTMyKGNvbEluKScpfVxuICAgICAgICB2YWx1ZSA9ICR7YVZhcmlhYmxlLmdldEJ5SW5kaWNlcygnYUluZGljZXMnKX07XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgZm4gbW1fcmVhZEIoYmF0Y2g6IGkzMiwgcm93OiBpMzIsIGNvbEluOiBpMzIsIGJhdGNoSW5kaWNlczogJHtiYXRjaFZhcmlhYmxlLnR5cGUuaW5kaWNlc30pIC0+ICR7dHlwZVNuaXBwZXQoXG4gICAgICBjb21wb25lbnQsXG4gICAgICBkYXRhVHlwZSxcbiAgICApfSB7XG4gICAgICB2YXIgdmFsdWUgPSAke3R5cGVTbmlwcGV0KGNvbXBvbmVudCwgZGF0YVR5cGUpfSgwLjApO1xuICAgICAgbGV0IGNvbCA9IGNvbEluICogJHtjb21wb25lbnR9O1xuICAgICAgaWYocm93IDwgdW5pZm9ybXMuZGltX2lubmVyICYmIGNvbCA8IHVuaWZvcm1zLmRpbV9iX291dGVyKVxuICAgICAge1xuICAgICAgICB2YXIgYkluZGljZXM6ICR7YlZhcmlhYmxlLnR5cGUuaW5kaWNlc307XG4gICAgICAgICR7Y29udmVydE91dHB1dEJhdGNoSW5kaWNlc1RvSW5wdXRCYXRjaEluZGljZXMoXG4gICAgICAgICAgJ2JJbmRpY2VzJyxcbiAgICAgICAgICBiVmFyaWFibGUsXG4gICAgICAgICAgYlZhcmlhYmxlLnJhbmsgLSAyLFxuICAgICAgICAgIGJhdGNoVmFyaWFibGUucmFuayxcbiAgICAgICAgICAnYmF0Y2hJbmRpY2VzJyxcbiAgICAgICAgKX1cbiAgICAgICAgJHtiVmFyaWFibGUuaW5kaWNlc1NldCgnYkluZGljZXMnLCBiVmFyaWFibGUucmFuayAtIDIsICd1MzIocm93KScpfVxuICAgICAgICAke2JWYXJpYWJsZS5pbmRpY2VzU2V0KCdiSW5kaWNlcycsIGJWYXJpYWJsZS5yYW5rIC0gMSwgJ3UzMihjb2xJbiknKX1cbiAgICAgICAgdmFsdWUgPSAke2JWYXJpYWJsZS5nZXRCeUluZGljZXMoJ2JJbmRpY2VzJyl9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIGZuIG1tX3dyaXRlKGJhdGNoOiBpMzIsIHJvdzogaTMyLCBjb2xJbjogaTMyLCB2YWx1ZUluOiAke3R5cGVTbmlwcGV0KGNvbXBvbmVudCwgZGF0YVR5cGUpfSkge1xuICAgICAgbGV0IGNvbCA9IGNvbEluICogJHtjb21wb25lbnR9O1xuICAgICAgaWYgKHJvdyA8IHVuaWZvcm1zLmRpbV9hX291dGVyICYmIGNvbCA8IHVuaWZvcm1zLmRpbV9iX291dGVyKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IHZhbHVlSW47XG4gICAgICAgIGxldCBjb29yZHMgPSB2ZWMzPGkzMj4oYmF0Y2gsIHJvdywgY29sSW4pO1xuICAgICAgICAke1xuICAgICAgICAgIGhhc0JpYXNcbiAgICAgICAgICAgID8gYHZhbHVlID0gdmFsdWUgKyAke2lzQ2hhbm5lbHNMYXN0ID8gJ2JpYXNbY29sSW5dJyA6IGAke3R5cGVTbmlwcGV0KGNvbXBvbmVudCwgZGF0YVR5cGUpfShiaWFzW3Jvd10pYH07YFxuICAgICAgICAgICAgOiAnJ1xuICAgICAgICB9XG4gICAgICAgICR7YXBwbHlBY3RpdmF0aW9ufVxuICAgICAgICAke291dHB1dFZhcmlhYmxlLnNldEJ5SW5kaWNlcygndmVjMzx1MzI+KGNvb3JkcyknLCAndmFsdWUnKX1cbiAgICAgIH1cbiAgICB9XG4gICAgYDtcbiAgcmV0dXJuIHNvdXJjZTtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVNYXRtdWxQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGFjdGl2YXRpb25BdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzLFxuICBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHJlc2hhcGVkT3V0cHV0U2hhcGU/OiByZWFkb25seSBudW1iZXJbXSxcbiAgaXNDaGFubmVsc0xhc3QgPSBmYWxzZSAvKiBvbmx5IHVzZWQgZm9yIGNvbnYyZEJ5TWF0TXVsKi8sXG4gIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uPzogKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSkgPT4gbnVtYmVyW10sXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGFTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBiU2hhcGUgPSBpbnB1dHNbMV0uZGltcztcbiAgY29uc3Qgb3V0ZXJEaW1zQSA9IGFTaGFwZS5zbGljZSgwLCAtMik7XG4gIGNvbnN0IG91dGVyRGltc0IgPSBiU2hhcGUuc2xpY2UoMCwgLTIpO1xuICBjb25zdCBvdXRlckRpbXMgPSByZXNoYXBlZE91dHB1dFNoYXBlID8gcmVzaGFwZWRPdXRwdXRTaGFwZS5zbGljZSgwLCAtMikgOiBvdXRwdXRTaGFwZS5zbGljZSgwLCAtMik7XG4gIGNvbnN0IGJhdGNoU2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dGVyRGltcyk7XG4gIGNvbnN0IGRpbUFPdXRlciA9IGFTaGFwZVthU2hhcGUubGVuZ3RoIC0gMl07XG4gIGNvbnN0IGRpbUlubmVyID0gYVNoYXBlW2FTaGFwZS5sZW5ndGggLSAxXTtcbiAgY29uc3QgZGltQk91dGVyID0gYlNoYXBlW2JTaGFwZS5sZW5ndGggLSAxXTtcbiAgY29uc3QgaXNWZWM0ID0gZGltSW5uZXIgJSA0ID09PSAwICYmIGRpbUJPdXRlciAlIDQgPT09IDA7XG5cbiAgLy8gVE9ETzogZmluZSB0dW5lIHNpemVcbiAgY29uc3QgZWxlbWVudHNQZXJUaHJlYWQgPSBkaW1BT3V0ZXIgPD0gOCA/IFs0LCAxLCAxXSA6IFs0LCA0LCAxXTtcbiAgY29uc3Qgd29ya2dyb3VwU2l6ZTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdID0gWzgsIDgsIDFdO1xuICBjb25zdCBkaXNwYXRjaCA9IFtcbiAgICBNYXRoLmNlaWwoZGltQk91dGVyIC8gd29ya2dyb3VwU2l6ZVswXSAvIGVsZW1lbnRzUGVyVGhyZWFkWzBdKSxcbiAgICBNYXRoLmNlaWwoZGltQU91dGVyIC8gd29ya2dyb3VwU2l6ZVsxXSAvIGVsZW1lbnRzUGVyVGhyZWFkWzFdKSxcbiAgICBNYXRoLmNlaWwoYmF0Y2hTaXplIC8gd29ya2dyb3VwU2l6ZVsyXSAvIGVsZW1lbnRzUGVyVGhyZWFkWzJdKSxcbiAgXTtcblxuICBjb25zdCBjb21wb25lbnRzID0gaXNWZWM0ID8gNCA6IDE7XG4gIGNvbnN0IGFTaGFwZVRlbXAgPSBbLi4ub3V0ZXJEaW1zQSwgZGltQU91dGVyLCBkaW1Jbm5lciAvIGNvbXBvbmVudHNdO1xuICBjb25zdCBhUmFuayA9IGFTaGFwZVRlbXAubGVuZ3RoO1xuICBjb25zdCBiU2hhcGVUZW1wID0gWy4uLm91dGVyRGltc0IsIGRpbUlubmVyLCBkaW1CT3V0ZXIgLyBjb21wb25lbnRzXTtcbiAgY29uc3QgYlJhbmsgPSBiU2hhcGVUZW1wLmxlbmd0aDtcbiAgY29uc3Qgb3V0cHV0U2hhcGVUZW1wID0gW2JhdGNoU2l6ZSwgZGltQU91dGVyLCBkaW1CT3V0ZXIgLyBjb21wb25lbnRzXTtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IGRpbUFPdXRlciB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IGRpbUJPdXRlciB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IGRpbUlubmVyIH0sXG4gIF07XG4gIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3Jtc0RhdGEoYWN0aXZhdGlvbkF0dHJpYnV0ZXMsIHByb2dyYW1Vbmlmb3Jtcyk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dGVyRGltcywgYVNoYXBlVGVtcCwgYlNoYXBlVGVtcCkpO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsncmFuaycsICdyYW5rJ107XG5cbiAgY29uc3QgaGFzQmlhcyA9IGlucHV0cy5sZW5ndGggPiAyO1xuICBpZiAoaGFzQmlhcykge1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1syXS5kaW1zKSk7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgncmFuaycpO1xuICB9XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dHB1dFNoYXBlVGVtcCkpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGJhdGNoUmFuayA9IG91dGVyRGltcy5sZW5ndGg7XG4gICAgY29uc3QgYmF0Y2hEaW1zID0gaW50ZXJuYWxWYXJpYWJsZSgnYmF0Y2hEaW1zJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBiYXRjaFJhbmssIDEpO1xuICAgIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKGlucHV0c1swXS5kYXRhVHlwZSk7XG5cbiAgICBjb25zdCBBID0gaW5wdXRWYXJpYWJsZSgnYScsIGlucHV0c1swXS5kYXRhVHlwZSwgYVJhbmssIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IEIgPSBpbnB1dFZhcmlhYmxlKCdiJywgaW5wdXRzWzFdLmRhdGFUeXBlLCBiUmFuaywgY29tcG9uZW50cyk7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ3Jlc3VsdCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGVUZW1wLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3QgaW5wdXRWYXJpYWJsZXMgPSBbQSwgQl07XG4gICAgaWYgKGhhc0JpYXMpIHtcbiAgICAgIGNvbnN0IGJpYXNDb21wb25lbnRzID0gaXNDaGFubmVsc0xhc3QgPyBjb21wb25lbnRzIDogMTtcbiAgICAgIGlucHV0VmFyaWFibGVzLnB1c2goaW5wdXRWYXJpYWJsZSgnYmlhcycsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMubGVuZ3RoLCBiaWFzQ29tcG9uZW50cykpO1xuICAgIH1cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdkaW1fYV9vdXRlcicsIHR5cGU6ICdpMzInIH0sXG4gICAgICB7IG5hbWU6ICdkaW1fYl9vdXRlcicsIHR5cGU6ICdpMzInIH0sXG4gICAgICB7IG5hbWU6ICdkaW1faW5uZXInLCB0eXBlOiAnaTMyJyB9LFxuICAgIF07XG4gICAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zKGFjdGl2YXRpb25BdHRyaWJ1dGVzLCB1bmlmb3Jtcyk7XG4gICAgY29uc3QgYmFzZVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUob3V0cHV0LnR5cGUudGVuc29yKTtcbiAgICBjb25zdCBhcHBseUFjdGl2YXRpb24gPSBnZXRBY3RpdmF0aW9uU25pcHBldChhY3RpdmF0aW9uQXR0cmlidXRlcywgb3V0cHV0LnR5cGUudmFsdWUsIGJhc2VUeXBlKTtcbiAgICBjb25zdCBkZWNsYXJlRnVuY3Rpb25zID0gbWF0TXVsUmVhZFdyaXRlRm5Tb3VyY2UoXG4gICAgICBjb21wb25lbnRzLFxuICAgICAgaGFzQmlhcyxcbiAgICAgIGFwcGx5QWN0aXZhdGlvbixcbiAgICAgIFtiYXRjaERpbXMsIEEsIEIsIG91dHB1dF0sXG4gICAgICBpc0NoYW5uZWxzTGFzdCxcbiAgICApO1xuICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyXG4gICAgLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpXG4gICAgLnJlZ2lzdGVySW50ZXJuYWxWYXJpYWJsZXMoYmF0Y2hEaW1zKVxuICAgIC5kZWNsYXJlVmFyaWFibGVzKC4uLmlucHV0VmFyaWFibGVzLCBvdXRwdXQpfVxuICAke2RlY2xhcmVGdW5jdGlvbnN9XG4gICR7XG4gICAgaXNWZWM0XG4gICAgICA/IG1ha2VNYXRNdWxQYWNrZWRWZWM0U291cmNlKGVsZW1lbnRzUGVyVGhyZWFkLCB3b3JrZ3JvdXBTaXplLCBkYXRhVHlwZSwgYmF0Y2hEaW1zKVxuICAgICAgOiBtYWtlTWF0TXVsUGFja2VkU291cmNlKGVsZW1lbnRzUGVyVGhyZWFkLCB3b3JrZ3JvdXBTaXplLCBkYXRhVHlwZSwgYmF0Y2hEaW1zKVxuICB9XG4gICAgICAgICAgICAgICAgICAgYDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnTWF0TXVsJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7ZWxlbWVudHNQZXJUaHJlYWR9OyR7YWN0aXZhdGlvbkF0dHJpYnV0ZXMuYWN0aXZhdGlvbn07JHtpc1ZlYzR9OyR7aXNDaGFubmVsc0xhc3R9YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGRpbXM6IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uID8gc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24ob3V0cHV0U2hhcGUpIDogb3V0cHV0U2hhcGUsXG4gICAgICAgICAgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IGRpc3BhdGNoWzBdLCB5OiBkaXNwYXRjaFsxXSwgejogZGlzcGF0Y2hbMl0gfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuLy8gc2FtcGxlZCBmcm9tIFtAdGVuc29yZmxvdy90ZmpzXSB0ZmpzLWJhY2tlbmQtd2ViZ3B1L3NyYy9jb252MmRfbW1fd2ViZ3B1LnRzXG4vL1xuLy8gbW9kaWZpZWQgdG8gZml0IHRoZSBuZWVkcyBvZiB0aGUgcHJvamVjdFxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IExPR19ERUJVRyB9IGZyb20gJy4uLy4uLy4uL2xvZyc7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgUHJvZ3JhbUluZm8sIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uLy4uL3R5cGVzJztcbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuLi9jb21tb24nO1xuaW1wb3J0IHsgQ29udkF0dHJpYnV0ZXMgfSBmcm9tICcuLi9jb252JztcbmltcG9ydCB7IGFwcGVuZEFjdGl2YXRpb25Vbmlmb3JtcywgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zRGF0YSwgZ2V0QWN0aXZhdGlvblNuaXBwZXQgfSBmcm9tICcuLi9mdXNlLXV0aWxzJztcblxuaW1wb3J0IHsgYmlhc1NuaXBwZXQsIHR5cGVTbmlwcGV0IH0gZnJvbSAnLi9hY3RpdmF0aW9uX3V0aWwnO1xuaW1wb3J0IHsgdXRpbEZ1bmN0aW9ucyB9IGZyb20gJy4vY29udl91dGlsJztcbmltcG9ydCB7IG1ha2VNYXRNdWxQYWNrZWRTb3VyY2UsIG1ha2VNYXRNdWxQYWNrZWRWZWM0U291cmNlIH0gZnJvbSAnLi9tYXRtdWxfcGFja2VkX3dlYmdwdSc7XG5cbmNvbnN0IGNvbnYyZENvbW1vblNuaXBwZXQgPSAoXG4gIGlzQ2hhbm5lbHNMYXN0OiBib29sZWFuLFxuICBmaXRBT3V0ZXI6IGJvb2xlYW4sXG4gIGZpdEJPdXRlcjogYm9vbGVhbixcbiAgZml0SW5uZXI6IGJvb2xlYW4sXG4gIGFkZEJpYXMgPSBmYWxzZSxcbiAgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMsXG4gIGlubmVyRWxlbWVudFNpemVYID0gNCxcbiAgaW5uZXJFbGVtZW50U2l6ZVcgPSA0LFxuICBpbm5lckVsZW1lbnRTaXplID0gNCxcbiAgZGF0YVR5cGUgPSAnZjMyJyxcbik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGdldFhTbmlwcGV0ID0gKGlubmVyRWxlbWVudFNpemU6IG51bWJlcikgPT4ge1xuICAgIHN3aXRjaCAoaW5uZXJFbGVtZW50U2l6ZSkge1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gJ3Jlc0RhdGEgPSB4W3hJbmRleF07JztcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgcmV0dXJuIGByZXNEYXRhID0gdmVjMzwke2RhdGFUeXBlfT4oeFt4SW5kZXhdLCB4W3hJbmRleCArIDFdLCB4W3hJbmRleCArIDJdKTtgO1xuICAgICAgY2FzZSA0OlxuICAgICAgICByZXR1cm4gJ3Jlc0RhdGEgPSB4W3hJbmRleCAvIDRdOyc7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGlubmVyRWxlbWVudFNpemUgJHtpbm5lckVsZW1lbnRTaXplfSBpcyBub3Qgc3VwcG9ydGVkLmApO1xuICAgIH1cbiAgfTtcbiAgY29uc3QgZ2V0V1NuaXBwZXQgPSAoaW5uZXJFbGVtZW50U2l6ZTogbnVtYmVyKSA9PiB7XG4gICAgc3dpdGNoIChpbm5lckVsZW1lbnRTaXplKSB7XG4gICAgICBjYXNlIDE6XG4gICAgICAgIHJldHVybiAncmV0dXJuIHdbcm93ICogaTMyKHVuaWZvcm1zLndfc2hhcGVbM10pICsgY29sSW5dOyc7XG4gICAgICBjYXNlIDQ6XG4gICAgICAgIHJldHVybiAncmV0dXJuIHdbcm93ICogaTMyKHVuaWZvcm1zLndfc2hhcGVbM10pIC8gNCArIGNvbEluXTsnO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbm5lckVsZW1lbnRTaXplICR7aW5uZXJFbGVtZW50U2l6ZX0gaXMgbm90IHN1cHBvcnRlZC5gKTtcbiAgICB9XG4gIH07XG4gIGNvbnN0IGNvb3JkQVNuaXBwZXQgPSBpc0NoYW5uZWxzTGFzdFxuICAgID8gYFxuICAgIGxldCBjb29yZCA9IHZlYzQ8aTMyPihiYXRjaCwgeFJvdywgeENvbCwgeENoKTtcbiAgICBgXG4gICAgOiBgXG4gICAgbGV0IGNvb3JkID0gdmVjNDxpMzI+KGJhdGNoLCB4Q2gsIHhSb3csIHhDb2wpO1xuICAgIGA7XG5cbiAgY29uc3QgY29vcmRSZXNTbmlwcGV0ID0gaXNDaGFubmVsc0xhc3RcbiAgICA/IGBcbiAgICBsZXQgY29vcmRzID0gdmVjNDxpMzI+KFxuICAgICAgYmF0Y2gsXG4gICAgICByb3cgLyBvdXRXaWR0aCxcbiAgICAgIHJvdyAlIG91dFdpZHRoLFxuICAgICAgY29sKTtcbiAgICBgXG4gICAgOiBgXG4gICAgbGV0IGNvb3JkcyA9IHZlYzQ8aTMyPihcbiAgICAgIGJhdGNoLFxuICAgICAgcm93LFxuICAgICAgY29sIC8gb3V0V2lkdGgsXG4gICAgICBjb2wgJSBvdXRXaWR0aCk7XG4gICAgYDtcblxuICBjb25zdCB4SGVpZ2h0ID0gaXNDaGFubmVsc0xhc3QgPyAnaTMyKHVuaWZvcm1zLnhfc2hhcGVbMV0pJyA6ICdpMzIodW5pZm9ybXMueF9zaGFwZVsyXSknO1xuICBjb25zdCB4V2lkdGggPSBpc0NoYW5uZWxzTGFzdCA/ICdpMzIodW5pZm9ybXMueF9zaGFwZVsyXSknIDogJ2kzMih1bmlmb3Jtcy54X3NoYXBlWzNdKSc7XG4gIGNvbnN0IHJvdyA9IGlzQ2hhbm5lbHNMYXN0ID8gJ3JvdycgOiAnY29sJztcbiAgY29uc3QgY29sID0gaXNDaGFubmVsc0xhc3QgPyAnY29sJyA6ICdyb3cnO1xuICBjb25zdCByZWFkWFNuaXBwZXQgPSBgXG4gICAgbGV0IGluQ2hhbm5lbHMgPSBpMzIodW5pZm9ybXMud19zaGFwZVsyXSk7XG4gICAgbGV0IG91dFdpZHRoID0gJHtpc0NoYW5uZWxzTGFzdCA/ICdpMzIodW5pZm9ybXMucmVzdWx0X3NoYXBlWzJdKScgOiAnaTMyKHVuaWZvcm1zLnJlc3VsdF9zaGFwZVszXSknfTtcbiAgICBsZXQgb3V0Um93ID0gJHtyb3d9IC8gb3V0V2lkdGg7XG4gICAgbGV0IG91dENvbCA9ICR7cm93fSAlIG91dFdpZHRoO1xuXG4gICAgbGV0IFdSb3cgPSAke2NvbH0gLyAoaTMyKHVuaWZvcm1zLndfc2hhcGVbMV0pICogaW5DaGFubmVscyk7XG4gICAgbGV0IFdDb2wgPSAke2NvbH0gLyBpbkNoYW5uZWxzICUgaTMyKHVuaWZvcm1zLndfc2hhcGVbMV0pO1xuICAgIGxldCB4Um93ID0gb3V0Um93ICogdW5pZm9ybXMuc3RyaWRlWzBdICsgdW5pZm9ybXMuZGlsYXRpb25bMF0gKiBXUm93IC0gdW5pZm9ybXMucGFkWzBdO1xuICAgIGxldCB4Q29sID0gb3V0Q29sICogdW5pZm9ybXMuc3RyaWRlWzFdICsgdW5pZm9ybXMuZGlsYXRpb25bMV0gKiBXQ29sIC0gdW5pZm9ybXMucGFkWzFdO1xuICAgIGxldCB4Q2ggPSAke2NvbH0gJSBpbkNoYW5uZWxzO1xuICAgIHZhciByZXNEYXRhID0gJHt0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplWCwgZGF0YVR5cGUpfSgwLjApO1xuICAgIC8vIFRoZSBib3VuZHMgY2hlY2tpbmcgaXMgYWx3YXlzIG5lZWRlZCBzaW5jZSB3ZSB1c2UgaXQgdG8gcGFkIHplcm8gZm9yXG4gICAgLy8gdGhlICdzYW1lJyBwYWRkaW5nIHR5cGUuXG4gICAgaWYgKHhSb3cgPj0gMCAmJiB4Um93IDwgJHt4SGVpZ2h0fSAmJiB4Q29sID49IDAgJiYgeENvbCA8ICR7eFdpZHRofSkge1xuICAgICAgJHtjb29yZEFTbmlwcGV0fVxuICAgICAgbGV0IHhJbmRleCA9IGdldEluZGV4RnJvbUNvb3JkczREKGNvb3JkLCB2ZWM0PGkzMj4odW5pZm9ybXMueF9zaGFwZSkpO1xuICAgICAgJHtnZXRYU25pcHBldChpbm5lckVsZW1lbnRTaXplWCl9XG4gICAgfVxuICAgIHJldHVybiByZXNEYXRhO2A7XG5cbiAgY29uc3Qgc2FtcGxlWCA9IGlzQ2hhbm5lbHNMYXN0XG4gICAgPyBmaXRBT3V0ZXIgJiYgZml0SW5uZXJcbiAgICAgID8gYFxuICAgIGxldCBjb2wgPSBjb2xJbiAqICR7aW5uZXJFbGVtZW50U2l6ZVh9O1xuICAgICR7cmVhZFhTbmlwcGV0fWBcbiAgICAgIDogYFxuICAgIGxldCBjb2wgPSBjb2xJbiAqICR7aW5uZXJFbGVtZW50U2l6ZVh9O1xuICAgIGlmIChyb3cgPCB1bmlmb3Jtcy5kaW1fYV9vdXRlciAmJiBjb2wgPCB1bmlmb3Jtcy5kaW1faW5uZXIpIHtcbiAgICAgICR7cmVhZFhTbmlwcGV0fVxuICAgIH1cbiAgICByZXR1cm4gJHt0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplWCwgZGF0YVR5cGUpfSgwLjApO2BcbiAgICA6IGZpdElubmVyICYmIGZpdEJPdXRlclxuICAgICAgPyBgXG4gICAgbGV0IGNvbCA9IGNvbEluICogJHtpbm5lckVsZW1lbnRTaXplWH07XG4gICAgJHtyZWFkWFNuaXBwZXR9YFxuICAgICAgOiBgXG4gICAgbGV0IGNvbCA9IGNvbEluICogJHtpbm5lckVsZW1lbnRTaXplWH07XG4gICAgaWYgKHJvdyA8IHVuaWZvcm1zLmRpbV9pbm5lciAmJiBjb2wgPCB1bmlmb3Jtcy5kaW1fYl9vdXRlcikge1xuICAgICAgJHtyZWFkWFNuaXBwZXR9XG4gICAgfVxuICAgIHJldHVybiAke3R5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemVYLCBkYXRhVHlwZSl9KDAuMCk7YDtcblxuICBjb25zdCBzYW1wbGVXID0gaXNDaGFubmVsc0xhc3RcbiAgICA/IGZpdElubmVyICYmIGZpdEJPdXRlclxuICAgICAgPyBnZXRXU25pcHBldChpbm5lckVsZW1lbnRTaXplVylcbiAgICAgIDogYFxuICAgIGxldCBjb2wgPSBjb2xJbiAqICR7aW5uZXJFbGVtZW50U2l6ZVd9O1xuICAgIGlmIChyb3cgPCB1bmlmb3Jtcy5kaW1faW5uZXIgJiYgY29sIDwgdW5pZm9ybXMuZGltX2Jfb3V0ZXIpIHtcbiAgICAgICR7Z2V0V1NuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVcpfVxuICAgIH1cbiAgICByZXR1cm4gJHt0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplVywgZGF0YVR5cGUpfSgwLjApO2BcbiAgICA6IGBcbiAgICBsZXQgY29sID0gY29sSW4gKiAke2lubmVyRWxlbWVudFNpemVXfTtcbiAgICBpZiAocm93IDwgdW5pZm9ybXMuZGltX2lubmVyICYmIGNvbCA8IHVuaWZvcm1zLmRpbV9hX291dGVyKSB7XG4gICAgICAke2dldFdTbmlwcGV0KGlubmVyRWxlbWVudFNpemVXKX1cbiAgICB9XG4gICAgcmV0dXJuICR7dHlwZVNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVcsIGRhdGFUeXBlKX0oMC4wKTtgO1xuXG4gIGNvbnN0IHJlc1R5cGUgPSB0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplLCBkYXRhVHlwZSk7XG4gIGNvbnN0IGFUeXBlID0gaXNDaGFubmVsc0xhc3QgPyB0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplWCwgZGF0YVR5cGUpIDogdHlwZVNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVcsIGRhdGFUeXBlKTtcbiAgY29uc3QgYlR5cGUgPSBpc0NoYW5uZWxzTGFzdCA/IHR5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemVXLCBkYXRhVHlwZSkgOiB0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplWCwgZGF0YVR5cGUpO1xuICBjb25zdCBhcHBseUFjdGl2YXRpb24gPSBnZXRBY3RpdmF0aW9uU25pcHBldChhdHRyaWJ1dGVzLCByZXNUeXBlLCBkYXRhVHlwZSk7XG4gIGNvbnN0IHVzZXJDb2RlID0gYFxuICAgIGZuIG1tX3JlYWRBKGJhdGNoOiBpMzIsIHJvdyA6IGkzMiwgY29sSW4gOiBpMzIpIC0+ICR7YVR5cGV9IHtcbiAgICAgICR7aXNDaGFubmVsc0xhc3QgPyBzYW1wbGVYIDogc2FtcGxlV31cbiAgICB9XG5cbiAgICBmbiBtbV9yZWFkQihiYXRjaDogaTMyLCByb3cgOiBpMzIsIGNvbEluIDogaTMyKSAtPiAke2JUeXBlfSB7XG4gICAgICAke2lzQ2hhbm5lbHNMYXN0ID8gc2FtcGxlVyA6IHNhbXBsZVh9XG4gICAgfVxuXG4gICAgZm4gbW1fd3JpdGUoYmF0Y2g6IGkzMiwgcm93IDogaTMyLCBjb2xJbiA6IGkzMiwgdmFsdWVJbiA6ICR7cmVzVHlwZX0pIHtcbiAgICAgIGxldCBjb2wgPSBjb2xJbiAqICR7aW5uZXJFbGVtZW50U2l6ZX07XG4gICAgICBpZiAocm93IDwgdW5pZm9ybXMuZGltX2Ffb3V0ZXIgJiYgY29sIDwgdW5pZm9ybXMuZGltX2Jfb3V0ZXIpXG4gICAgICB7XG4gICAgICB2YXIgdmFsdWUgPSB2YWx1ZUluO1xuICAgICAgbGV0IG91dFdpZHRoID0gJHtpc0NoYW5uZWxzTGFzdCA/ICdpMzIodW5pZm9ybXMucmVzdWx0X3NoYXBlWzJdKScgOiAnaTMyKHVuaWZvcm1zLnJlc3VsdF9zaGFwZVszXSknfTtcbiAgICAgICR7Y29vcmRSZXNTbmlwcGV0fVxuICAgICAgJHtiaWFzU25pcHBldChhZGRCaWFzKX1cbiAgICAgICR7YXBwbHlBY3RpdmF0aW9ufVxuICAgICAgc2V0T3V0cHV0QXRDb29yZHMoY29vcmRzWzBdLCBjb29yZHNbMV0sIGNvb3Jkc1syXSwgY29vcmRzWzNdLCB2YWx1ZSk7XG4gICAgICB9XG4gICAgfWA7XG4gIHJldHVybiB1c2VyQ29kZTtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVDb252MkRNYXRNdWxQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzLFxuICBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGRpbUFPdXRlcjogbnVtYmVyLFxuICBkaW1CT3V0ZXI6IG51bWJlcixcbiAgZGltSW5uZXI6IG51bWJlcixcbiAgaGFzQmlhczogYm9vbGVhbixcbiAgc2VxdWVudGlhbEFjY2Vzc0J5VGhyZWFkczogYm9vbGVhbixcbiAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24/OiAoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKSA9PiBudW1iZXJbXSxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaXNDaGFubmVsc0xhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuICBjb25zdCBpbkNoYW5uZWxzID0gaXNDaGFubmVsc0xhc3QgPyBpbnB1dHNbMF0uZGltc1szXSA6IGlucHV0c1swXS5kaW1zWzFdO1xuICBjb25zdCBiYXRjaFNpemUgPSBvdXRwdXRTaGFwZVswXTtcbiAgY29uc3Qgb3V0V2lkdGggPSBpc0NoYW5uZWxzTGFzdCA/IG91dHB1dFNoYXBlWzJdIDogb3V0cHV0U2hhcGVbM107XG4gIGNvbnN0IG91dEhlaWdodCA9IGlzQ2hhbm5lbHNMYXN0ID8gb3V0cHV0U2hhcGVbMV0gOiBvdXRwdXRTaGFwZVsyXTtcbiAgY29uc3Qgb3V0Q2hhbm5lbHMgPSBpc0NoYW5uZWxzTGFzdCA/IG91dHB1dFNoYXBlWzNdIDogb3V0cHV0U2hhcGVbMV07XG4gIC8vIFRPRE86IGVuYWJsZSB2ZWM0IGZvciBOQ0hXXG4gIGNvbnN0IGlzVmVjNCA9IGlzQ2hhbm5lbHNMYXN0ICYmIChpbkNoYW5uZWxzICUgNCA9PT0gMCB8fCBpbkNoYW5uZWxzICUgMyA9PT0gMCkgJiYgb3V0Q2hhbm5lbHMgJSA0ID09PSAwO1xuXG4gIC8vIFRPRE86IGZpbmUgdHVuZSBzaXplXG4gIGNvbnN0IGRpc3BhdGNoWCA9IGlzQ2hhbm5lbHNMYXN0ID8gb3V0Q2hhbm5lbHMgOiBvdXRXaWR0aCAqIG91dEhlaWdodDtcbiAgY29uc3QgZGlzcGF0Y2hZID0gaXNDaGFubmVsc0xhc3QgPyBvdXRXaWR0aCAqIG91dEhlaWdodCA6IG91dENoYW5uZWxzO1xuICBjb25zdCB3b3JrR3JvdXBTaXplOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPSBbOCwgOCwgMV07XG4gIGNvbnN0IGVsZW1lbnRzUGVyVGhyZWFkID0gZGltQU91dGVyIDw9IDggPyBbNCwgMSwgMV0gOiBbNCwgNCwgMV07XG4gIGNvbnN0IGRpc3BhdGNoID0gW1xuICAgIE1hdGguY2VpbChkaXNwYXRjaFggLyB3b3JrR3JvdXBTaXplWzBdIC8gZWxlbWVudHNQZXJUaHJlYWRbMF0pLFxuICAgIE1hdGguY2VpbChkaXNwYXRjaFkgLyB3b3JrR3JvdXBTaXplWzFdIC8gZWxlbWVudHNQZXJUaHJlYWRbMV0pLFxuICAgIE1hdGguY2VpbChiYXRjaFNpemUgLyB3b3JrR3JvdXBTaXplWzJdIC8gZWxlbWVudHNQZXJUaHJlYWRbMl0pLFxuICBdO1xuXG4gIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbY29udjJkX21tX3dlYmdwdV0gZGlzcGF0Y2ggPSAke2Rpc3BhdGNofWApO1xuXG4gIGNvbnN0IGlubmVyRWxlbWVudFNpemUgPSBpc1ZlYzQgPyAoaXNDaGFubmVsc0xhc3QgJiYgaW5DaGFubmVscyAlIDQgIT09IDAgPyAzIDogNCkgOiAxO1xuICBjb25zdCB0aWxlQU91dGVyID0gd29ya0dyb3VwU2l6ZVsxXSAqIGVsZW1lbnRzUGVyVGhyZWFkWzFdO1xuICBjb25zdCB0aWxlQk91dGVyID0gd29ya0dyb3VwU2l6ZVswXSAqIGVsZW1lbnRzUGVyVGhyZWFkWzBdO1xuICBjb25zdCB0aWxlSW5uZXIgPSBNYXRoLm1heCh3b3JrR3JvdXBTaXplWzBdICogaW5uZXJFbGVtZW50U2l6ZSwgd29ya0dyb3VwU2l6ZVsxXSk7XG4gIGNvbnN0IGZpdEFPdXRlciA9IGRpbUFPdXRlciAlIHRpbGVBT3V0ZXIgPT09IDA7XG4gIGNvbnN0IGZpdEJPdXRlciA9IGRpbUJPdXRlciAlIHRpbGVCT3V0ZXIgPT09IDA7XG4gIGNvbnN0IGZpdElubmVyID0gZGltSW5uZXIgJSB0aWxlSW5uZXIgPT09IDA7XG4gIGNvbnN0IGVsZW1lbnRzU2l6ZSA9IGlzVmVjNCA/IFtpbm5lckVsZW1lbnRTaXplLCA0LCA0XSA6IFsxLCAxLCAxXTtcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogZGltQU91dGVyIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogZGltQk91dGVyIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogZGltSW5uZXIgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBbYXR0cmlidXRlcy5wYWRzWzBdLCBhdHRyaWJ1dGVzLnBhZHNbMV1dIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogYXR0cmlidXRlcy5zdHJpZGVzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogYXR0cmlidXRlcy5kaWxhdGlvbnMgfSxcbiAgXTtcbiAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zRGF0YShhdHRyaWJ1dGVzLCBwcm9ncmFtVW5pZm9ybXMpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMF0uZGltcywgaW5wdXRzWzFdLmRpbXMpKTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3JhbmsnLCAncmFuayddO1xuICBpZiAoaGFzQmlhcykge1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1syXS5kaW1zKSk7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgncmFuaycpO1xuICB9XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dHB1dFNoYXBlKSk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnZGltX2Ffb3V0ZXInLCB0eXBlOiAnaTMyJyB9LFxuICAgICAgeyBuYW1lOiAnZGltX2Jfb3V0ZXInLCB0eXBlOiAnaTMyJyB9LFxuICAgICAgeyBuYW1lOiAnZGltX2lubmVyJywgdHlwZTogJ2kzMicgfSxcbiAgICAgIHsgbmFtZTogJ3BhZCcsIHR5cGU6ICdpMzInLCBsZW5ndGg6IDIgfSxcbiAgICAgIHsgbmFtZTogJ3N0cmlkZScsIHR5cGU6ICdpMzInLCBsZW5ndGg6IDIgfSxcbiAgICAgIHsgbmFtZTogJ2RpbGF0aW9uJywgdHlwZTogJ2kzMicsIGxlbmd0aDogMiB9LFxuICAgIF07XG4gICAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zKGF0dHJpYnV0ZXMsIHVuaWZvcm1zKTtcblxuICAgIC8vIFRPRE86IHN1cHBvcnQgY29tcG9uZW50IDIsIDMuXG4gICAgY29uc3QgY29tcG9uZW50cyA9IGlzVmVjNCA/IDQgOiAxO1xuICAgIGNvbnN0IHQgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUoaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgICBsZXQgZGVjbGFyZUZ1bmN0aW9ucyA9IGBcbiAgICAgIGZuIHNldE91dHB1dEF0SW5kZXgoZmxhdEluZGV4IDogaTMyLCB2YWx1ZSA6ICR7aXNWZWM0ID8gYHZlYzQ8JHt0fT5gIDogdH0pIHtcbiAgICAgICAgcmVzdWx0W2ZsYXRJbmRleF0gPSAke2lzVmVjNCA/IGB2ZWM0PCR7dH0+YCA6IHR9KHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIGZuIHNldE91dHB1dEF0Q29vcmRzKGQwIDogaTMyLCBkMSA6IGkzMiwgZDIgOiBpMzIsIGQzIDogaTMyLCB2YWx1ZSA6ICR7aXNWZWM0ID8gYHZlYzQ8JHt0fT5gIDogdH0pIHtcbiAgICAgICAgbGV0IGZsYXRJbmRleCA9IGdldE91dHB1dEluZGV4RnJvbUNvb3Jkcyh2ZWM0PGkzMj4oZDAsIGQxLCBkMiwgZDMpKTtcbiAgICAgICAgc2V0T3V0cHV0QXRJbmRleChmbGF0SW5kZXggJHtpc1ZlYzQgPyAnLyA0JyA6ICcnfSwgdmFsdWUpO1xuICAgICAgfWA7XG4gICAgY29uc3QgeCA9IGlucHV0VmFyaWFibGUoXG4gICAgICAneCcsXG4gICAgICBpbnB1dHNbMF0uZGF0YVR5cGUsXG4gICAgICBpbnB1dHNbMF0uZGltcy5sZW5ndGgsXG4gICAgICBpbm5lckVsZW1lbnRTaXplID09PSAzID8gMSA6IGlubmVyRWxlbWVudFNpemUsXG4gICAgKTtcbiAgICBjb25zdCB3ID0gaW5wdXRWYXJpYWJsZSgndycsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBpbnB1dFZhcmlhYmxlcyA9IFt4LCB3XTtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgncmVzdWx0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGlmIChoYXNCaWFzKSB7XG4gICAgICBjb25zdCBiaWFzID0gaW5wdXRWYXJpYWJsZSgnYmlhcycsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICAgIGlucHV0VmFyaWFibGVzLnB1c2goYmlhcyk7XG4gICAgICBkZWNsYXJlRnVuY3Rpb25zICs9IGBcbiAgICAgICAgZm4gZ2V0Qmlhc0J5T3V0cHV0Q29vcmRzKGNvb3JkcyA6IHZlYzQ8aTMyPikgLT4gJHtpc1ZlYzQgPyBgdmVjNDwke3R9PmAgOiB0fSB7XG4gICAgICAgICAgcmV0dXJuIGJpYXNbY29vcmRzLiR7aXNDaGFubmVsc0xhc3QgPyAndycgOiAneSd9JHtpc1ZlYzQgPyAnLyA0JyA6ICcnfV07XG4gICAgICAgIH1gO1xuICAgIH1cblxuICAgIHJldHVybiBgXG4gICAgICAgICR7dXRpbEZ1bmN0aW9ucygndW5pZm9ybXMucmVzdWx0X3N0cmlkZXMnKX1cbiAgICAgICAgLy9zdHJ1Y3QgVW5pZm9ybXMgeyB4U2hhcGUgOiB2ZWM0PGkzMj4sIHdTaGFwZSA6IHZlYzQ8aTMyPiwgb3V0U2hhcGUgOiB2ZWM0PGkzMj4sXG4gICAgICAgIC8vICBvdXRTaGFwZVN0cmlkZXM6IHZlYzM8aTMyPiwgZmlsdGVyRGltcyA6IHZlYzI8aTMyPiwgcGFkIDogdmVjMjxpMzI+LCBzdHJpZGUgOiB2ZWMyPGkzMj4sXG4gICAgICAgIC8vICBkaWxhdGlvbiA6IHZlYzI8aTMyPiwgZGltQU91dGVyIDogaTMyLCBkaW1CT3V0ZXIgOiBpMzIsIGRpbUlubmVyIDogaTMyIH07XG4gICAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4uaW5wdXRWYXJpYWJsZXMsIG91dHB1dCl9XG4gICAgICAgICR7ZGVjbGFyZUZ1bmN0aW9uc31cbiAgICAgICAgJHtjb252MmRDb21tb25TbmlwcGV0KFxuICAgICAgICAgIGlzQ2hhbm5lbHNMYXN0LFxuICAgICAgICAgIGZpdEFPdXRlcixcbiAgICAgICAgICBmaXRCT3V0ZXIsXG4gICAgICAgICAgZml0SW5uZXIsXG4gICAgICAgICAgaGFzQmlhcyxcbiAgICAgICAgICBhdHRyaWJ1dGVzLFxuICAgICAgICAgIGVsZW1lbnRzU2l6ZVswXSxcbiAgICAgICAgICBlbGVtZW50c1NpemVbMV0sXG4gICAgICAgICAgZWxlbWVudHNTaXplWzJdLFxuICAgICAgICAgIHQsXG4gICAgICAgICl9XG4gICAgICAgICR7XG4gICAgICAgICAgaXNWZWM0XG4gICAgICAgICAgICA/IG1ha2VNYXRNdWxQYWNrZWRWZWM0U291cmNlKGVsZW1lbnRzUGVyVGhyZWFkLCB3b3JrR3JvdXBTaXplLCB0LCB1bmRlZmluZWQsICFpc0NoYW5uZWxzTGFzdCwgdGlsZUlubmVyKVxuICAgICAgICAgICAgOiBtYWtlTWF0TXVsUGFja2VkU291cmNlKFxuICAgICAgICAgICAgICAgIGVsZW1lbnRzUGVyVGhyZWFkLFxuICAgICAgICAgICAgICAgIHdvcmtHcm91cFNpemUsXG4gICAgICAgICAgICAgICAgdCxcbiAgICAgICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgIWlzQ2hhbm5lbHNMYXN0LFxuICAgICAgICAgICAgICAgIHRpbGVJbm5lcixcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgc2VxdWVudGlhbEFjY2Vzc0J5VGhyZWFkcyxcbiAgICAgICAgICAgICAgKVxuICAgICAgICB9YDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQ29udjJETWF0TXVsJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX07JHtpbm5lckVsZW1lbnRTaXplfTske2lzVmVjNH07JHtmaXRBT3V0ZXJ9OyR7Zml0Qk91dGVyfTske2ZpdElubmVyfTske3RpbGVBT3V0ZXJ9OyR7dGlsZUJPdXRlcn07JHt0aWxlSW5uZXJ9YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGRpbXM6IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uID8gc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24ob3V0cHV0U2hhcGUpIDogb3V0cHV0U2hhcGUsXG4gICAgICAgICAgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IGRpc3BhdGNoWzBdLCB5OiBkaXNwYXRjaFsxXSwgejogZGlzcGF0Y2hbMl0gfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuLy8gc2FtcGxlZCBmcm9tIFtAdGVuc29yZmxvdy90ZmpzXSB0ZmpzLWJhY2tlbmQtd2ViZ3B1L3NyYy9jb252M2RfbmFpdmVfd2ViZ3B1LnRzXG4vL1xuLy8gbW9kaWZpZWQgdG8gZml0IHRoZSBuZWVkcyBvZiB0aGUgcHJvamVjdFxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IExPR19ERUJVRyB9IGZyb20gJy4uLy4uLy4uL2xvZyc7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBQcm9ncmFtSW5mbywgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGdldEVsZW1lbnRBdCxcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlLFxuICBVbmlmb3Jtc0FycmF5VHlwZSxcbn0gZnJvbSAnLi4vY29tbW9uJztcbmltcG9ydCB7IENvbnZBdHRyaWJ1dGVzIH0gZnJvbSAnLi4vY29udic7XG5pbXBvcnQgeyBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXMsIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3Jtc0RhdGEsIGdldEFjdGl2YXRpb25TbmlwcGV0IH0gZnJvbSAnLi4vZnVzZS11dGlscyc7XG5cbmltcG9ydCB7IHR5cGVTbmlwcGV0IH0gZnJvbSAnLi9hY3RpdmF0aW9uX3V0aWwnO1xuXG5jb25zdCBhcnJheVByb2R1Y3QgPSAoYXJyOiBudW1iZXJbXSkgPT4ge1xuICBsZXQgcHJvZHVjdCA9IDE7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgcHJvZHVjdCAqPSBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHByb2R1Y3Q7XG59O1xuXG5jb25zdCBwYXJzZTNUdXBsZVBhcmFtID0gKHBhcmFtOiBudW1iZXIgfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPT5cbiAgdHlwZW9mIHBhcmFtID09PSAnbnVtYmVyJyA/IFtwYXJhbSwgcGFyYW0sIHBhcmFtXSA6IHBhcmFtO1xuXG5jb25zdCBnZXRFZmZlY3RpdmVGaWx0ZXJTaXplID0gKGZpbHRlclNpemU6IG51bWJlciwgZGlsYXRpb246IG51bWJlcik6IG51bWJlciA9PiB7XG4gIGlmIChkaWxhdGlvbiA8PSAxKSB7XG4gICAgcmV0dXJuIGZpbHRlclNpemU7XG4gIH1cblxuICByZXR1cm4gZmlsdGVyU2l6ZSArIChmaWx0ZXJTaXplIC0gMSkgKiAoZGlsYXRpb24gLSAxKTtcbn07XG5cbmNvbnN0IGNvbXB1dGVEZWZhdWx0UGFkID0gKFxuICBpbnB1dFNoYXBlOiBbbnVtYmVyLCBudW1iZXJdIHwgW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gIGZpZWxkU2l6ZTogbnVtYmVyLFxuICBzdHJpZGU6IG51bWJlcixcbiAgZGlsYXRpb24gPSAxLFxuKTogbnVtYmVyID0+IHtcbiAgY29uc3QgZWZmZWN0aXZlRmllbGRTaXplID0gZ2V0RWZmZWN0aXZlRmlsdGVyU2l6ZShmaWVsZFNpemUsIGRpbGF0aW9uKTtcbiAgcmV0dXJuIE1hdGguZmxvb3IoKGlucHV0U2hhcGVbMF0gKiAoc3RyaWRlIC0gMSkgLSBzdHJpZGUgKyBlZmZlY3RpdmVGaWVsZFNpemUpIC8gMik7XG59O1xuXG5jb25zdCBjb21wdXRlT3V0cHV0U2hhcGU0RCA9IChcbiAgaW5TaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gIGZpbHRlclNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gIG91dENoYW5uZWxzOiBudW1iZXIsXG4gIHN0cmlkZXM6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgemVyb1BhZD86IG51bWJlcixcbik6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdID0+IHtcbiAgaWYgKHplcm9QYWQgPT0gbnVsbCkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1wYXJhbS1yZWFzc2lnblxuICAgIHplcm9QYWQgPSBjb21wdXRlRGVmYXVsdFBhZChpblNoYXBlLCBmaWx0ZXJTaGFwZVswXSwgc3RyaWRlc1swXSk7XG4gIH1cbiAgY29uc3Qgb3V0U2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdID0gWzAsIDAsIDAsIG91dENoYW5uZWxzXTtcbiAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IDM7IGluZGV4KyspIHtcbiAgICBpZiAoaW5TaGFwZVtpbmRleF0gKyAyICogemVyb1BhZCA+PSBmaWx0ZXJTaGFwZVtpbmRleF0pIHtcbiAgICAgIG91dFNoYXBlW2luZGV4XSA9IE1hdGgudHJ1bmMoKGluU2hhcGVbaW5kZXhdIC0gZmlsdGVyU2hhcGVbaW5kZXhdICsgMiAqIHplcm9QYWQpIC8gc3RyaWRlc1tpbmRleF0gKyAxKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dFNoYXBlO1xufTtcblxuY29uc3QgZ2V0M0RQYWRBbmRPdXRJbmZvID0gKFxuICBwYWQ6IG51bWJlciB8IHN0cmluZyB8IG51bWJlcltdLFxuICBpbkRlcHRoOiBudW1iZXIsXG4gIGluSGVpZ2h0OiBudW1iZXIsXG4gIGluV2lkdGg6IG51bWJlcixcbiAgc3RyaWRlRGVwdGg6IG51bWJlcixcbiAgc3RyaWRlSGVpZ2h0OiBudW1iZXIsXG4gIHN0cmlkZVdpZHRoOiBudW1iZXIsXG4gIGZpbHRlckRlcHRoOiBudW1iZXIsXG4gIGZpbHRlckhlaWdodDogbnVtYmVyLFxuICBmaWx0ZXJXaWR0aDogbnVtYmVyLFxuKTogeyBwYWRJbmZvOiBQYWRJbmZvM0Q7IG91dERlcHRoOiBudW1iZXI7IG91dEhlaWdodDogbnVtYmVyOyBvdXRXaWR0aDogbnVtYmVyIH0gPT4ge1xuICBsZXQgcGFkSW5mbzogUGFkSW5mbzNEO1xuICBsZXQgb3V0RGVwdGg6IG51bWJlcjtcbiAgbGV0IG91dEhlaWdodDogbnVtYmVyO1xuICBsZXQgb3V0V2lkdGg6IG51bWJlcjtcblxuICBpZiAocGFkID09PSAnVkFMSUQnKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXBhcmFtLXJlYXNzaWduXG4gICAgcGFkID0gMDtcbiAgfVxuXG4gIGlmICh0eXBlb2YgcGFkID09PSAnbnVtYmVyJykge1xuICAgIHBhZEluZm8gPSB7IHRvcDogcGFkLCBib3R0b206IHBhZCwgbGVmdDogcGFkLCByaWdodDogcGFkLCBmcm9udDogcGFkLCBiYWNrOiBwYWQgfTtcbiAgICBjb25zdCBvdXRTaGFwZSA9IGNvbXB1dGVPdXRwdXRTaGFwZTREKFxuICAgICAgW2luRGVwdGgsIGluSGVpZ2h0LCBpbldpZHRoLCAxXSxcbiAgICAgIFtmaWx0ZXJEZXB0aCwgZmlsdGVySGVpZ2h0LCBmaWx0ZXJXaWR0aF0sXG4gICAgICAxLFxuICAgICAgW3N0cmlkZURlcHRoLCBzdHJpZGVIZWlnaHQsIHN0cmlkZVdpZHRoXSxcbiAgICAgIHBhZCxcbiAgICApO1xuICAgIG91dERlcHRoID0gb3V0U2hhcGVbMF07XG4gICAgb3V0SGVpZ2h0ID0gb3V0U2hhcGVbMV07XG4gICAgb3V0V2lkdGggPSBvdXRTaGFwZVsyXTtcbiAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHBhZCkpIHtcbiAgICBpZiAoIXBhZC5ldmVyeSgodmFsLCBfLCBhcnIpID0+IHZhbCA9PT0gYXJyWzBdKSkge1xuICAgICAgdGhyb3cgRXJyb3IoYFVuc3VwcG9ydGVkIHBhZGRpbmcgcGFyYW1ldGVyOiAke3BhZH1gKTtcbiAgICB9XG4gICAgcGFkSW5mbyA9IHsgdG9wOiBwYWRbMF0sIGJvdHRvbTogcGFkWzFdLCBsZWZ0OiBwYWRbMl0sIHJpZ2h0OiBwYWRbM10sIGZyb250OiBwYWRbNF0sIGJhY2s6IHBhZFs1XSB9O1xuICAgIGNvbnN0IG91dFNoYXBlID0gY29tcHV0ZU91dHB1dFNoYXBlNEQoXG4gICAgICBbaW5EZXB0aCwgaW5IZWlnaHQsIGluV2lkdGgsIDFdLFxuICAgICAgW2ZpbHRlckRlcHRoLCBmaWx0ZXJIZWlnaHQsIGZpbHRlcldpZHRoXSxcbiAgICAgIDEsXG4gICAgICBbc3RyaWRlRGVwdGgsIHN0cmlkZUhlaWdodCwgc3RyaWRlV2lkdGhdLFxuICAgICAgcGFkWzBdLFxuICAgICk7XG4gICAgb3V0RGVwdGggPSBvdXRTaGFwZVswXTtcbiAgICBvdXRIZWlnaHQgPSBvdXRTaGFwZVsxXTtcbiAgICBvdXRXaWR0aCA9IG91dFNoYXBlWzJdO1xuICB9IGVsc2UgaWYgKHBhZCA9PT0gJ1NBTUVfVVBQRVInKSB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCAnU0FNRV9MT1dFUicuXG4gICAgb3V0RGVwdGggPSBNYXRoLmNlaWwoaW5EZXB0aCAvIHN0cmlkZURlcHRoKTtcbiAgICBvdXRIZWlnaHQgPSBNYXRoLmNlaWwoaW5IZWlnaHQgLyBzdHJpZGVIZWlnaHQpO1xuICAgIG91dFdpZHRoID0gTWF0aC5jZWlsKGluV2lkdGggLyBzdHJpZGVXaWR0aCk7XG4gICAgY29uc3QgcGFkQWxvbmdEZXB0aCA9IChvdXREZXB0aCAtIDEpICogc3RyaWRlRGVwdGggKyBmaWx0ZXJEZXB0aCAtIGluRGVwdGg7XG4gICAgY29uc3QgcGFkQWxvbmdIZWlnaHQgPSAob3V0SGVpZ2h0IC0gMSkgKiBzdHJpZGVIZWlnaHQgKyBmaWx0ZXJIZWlnaHQgLSBpbkhlaWdodDtcbiAgICBjb25zdCBwYWRBbG9uZ1dpZHRoID0gKG91dFdpZHRoIC0gMSkgKiBzdHJpZGVXaWR0aCArIGZpbHRlcldpZHRoIC0gaW5XaWR0aDtcbiAgICBjb25zdCBmcm9udCA9IE1hdGguZmxvb3IocGFkQWxvbmdEZXB0aCAvIDIpO1xuICAgIGNvbnN0IGJhY2sgPSBwYWRBbG9uZ0RlcHRoIC0gZnJvbnQ7XG4gICAgY29uc3QgdG9wID0gTWF0aC5mbG9vcihwYWRBbG9uZ0hlaWdodCAvIDIpO1xuICAgIGNvbnN0IGJvdHRvbSA9IHBhZEFsb25nSGVpZ2h0IC0gdG9wO1xuICAgIGNvbnN0IGxlZnQgPSBNYXRoLmZsb29yKHBhZEFsb25nV2lkdGggLyAyKTtcbiAgICBjb25zdCByaWdodCA9IHBhZEFsb25nV2lkdGggLSBsZWZ0O1xuXG4gICAgcGFkSW5mbyA9IHsgdG9wLCBib3R0b20sIGxlZnQsIHJpZ2h0LCBmcm9udCwgYmFjayB9O1xuICB9IGVsc2Uge1xuICAgIHRocm93IEVycm9yKGBVbmtub3duIHBhZGRpbmcgcGFyYW1ldGVyOiAke3BhZH1gKTtcbiAgfVxuICByZXR1cm4geyBwYWRJbmZvLCBvdXREZXB0aCwgb3V0SGVpZ2h0LCBvdXRXaWR0aCB9O1xufTtcblxudHlwZSBQYWRJbmZvM0QgPSB7XG4gIHRvcDogbnVtYmVyO1xuICBsZWZ0OiBudW1iZXI7XG4gIHJpZ2h0OiBudW1iZXI7XG4gIGJvdHRvbTogbnVtYmVyO1xuICBmcm9udDogbnVtYmVyO1xuICBiYWNrOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBDb252M0RJbmZvID0ge1xuICBiYXRjaFNpemU6IG51bWJlcjtcbiAgaW5EZXB0aDogbnVtYmVyO1xuICBpbkhlaWdodDogbnVtYmVyO1xuICBpbldpZHRoOiBudW1iZXI7XG4gIGluQ2hhbm5lbHM6IG51bWJlcjtcbiAgb3V0RGVwdGg6IG51bWJlcjtcbiAgb3V0SGVpZ2h0OiBudW1iZXI7XG4gIG91dFdpZHRoOiBudW1iZXI7XG4gIG91dENoYW5uZWxzOiBudW1iZXI7XG4gIGRhdGFGb3JtYXQ6ICdjaGFubmVsc0ZpcnN0JyB8ICdjaGFubmVsc0xhc3QnO1xuICBzdHJpZGVEZXB0aDogbnVtYmVyO1xuICBzdHJpZGVIZWlnaHQ6IG51bWJlcjtcbiAgc3RyaWRlV2lkdGg6IG51bWJlcjtcbiAgZGlsYXRpb25EZXB0aDogbnVtYmVyO1xuICBkaWxhdGlvbkhlaWdodDogbnVtYmVyO1xuICBkaWxhdGlvbldpZHRoOiBudW1iZXI7XG4gIGZpbHRlckRlcHRoOiBudW1iZXI7XG4gIGZpbHRlckhlaWdodDogbnVtYmVyO1xuICBmaWx0ZXJXaWR0aDogbnVtYmVyO1xuICBlZmZlY3RpdmVGaWx0ZXJEZXB0aDogbnVtYmVyO1xuICBlZmZlY3RpdmVGaWx0ZXJIZWlnaHQ6IG51bWJlcjtcbiAgZWZmZWN0aXZlRmlsdGVyV2lkdGg6IG51bWJlcjtcbiAgcGFkSW5mbzogUGFkSW5mbzNEO1xuICBpblNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICBvdXRTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgZmlsdGVyU2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG59O1xuXG5leHBvcnQgY29uc3QgY29tcHV0ZUNvbnYzREluZm8gPSAoXG4gIGluU2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gIGZpbHRlclNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICBzdHJpZGVzOiBudW1iZXIgfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gIGRpbGF0aW9uczogbnVtYmVyIHwgW251bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICBwYWQ6IG51bWJlciB8IHN0cmluZyB8IG51bWJlcltdLFxuICBkZXB0aHdpc2UgPSBmYWxzZSxcbiAgZGF0YUZvcm1hdDogJ2NoYW5uZWxzRmlyc3QnIHwgJ2NoYW5uZWxzTGFzdCcgPSAnY2hhbm5lbHNMYXN0Jyxcbik6IENvbnYzREluZm8gPT4ge1xuICBsZXQgYmF0Y2hTaXplLCBpbkRlcHRoLCBpbkhlaWdodCwgaW5XaWR0aCwgaW5DaGFubmVscztcbiAgaWYgKGRhdGFGb3JtYXQgPT09ICdjaGFubmVsc0xhc3QnKSB7XG4gICAgW2JhdGNoU2l6ZSwgaW5EZXB0aCwgaW5IZWlnaHQsIGluV2lkdGgsIGluQ2hhbm5lbHNdID0gaW5TaGFwZTtcbiAgfSBlbHNlIGlmIChkYXRhRm9ybWF0ID09PSAnY2hhbm5lbHNGaXJzdCcpIHtcbiAgICBbYmF0Y2hTaXplLCBpbkNoYW5uZWxzLCBpbkRlcHRoLCBpbkhlaWdodCwgaW5XaWR0aF0gPSBpblNoYXBlO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBkYXRhRm9ybWF0ICR7ZGF0YUZvcm1hdH1gKTtcbiAgfVxuICBjb25zdCBbZmlsdGVyQ2hhbm5lbHMsICwgZmlsdGVyRGVwdGgsIGZpbHRlckhlaWdodCwgZmlsdGVyV2lkdGhdID0gZmlsdGVyU2hhcGU7XG5cbiAgY29uc3QgW3N0cmlkZURlcHRoLCBzdHJpZGVIZWlnaHQsIHN0cmlkZVdpZHRoXSA9IHBhcnNlM1R1cGxlUGFyYW0oc3RyaWRlcyk7XG4gIGNvbnN0IFtkaWxhdGlvbkRlcHRoLCBkaWxhdGlvbkhlaWdodCwgZGlsYXRpb25XaWR0aF0gPSBwYXJzZTNUdXBsZVBhcmFtKGRpbGF0aW9ucyk7XG5cbiAgY29uc3QgZWZmZWN0aXZlRmlsdGVyRGVwdGggPSBnZXRFZmZlY3RpdmVGaWx0ZXJTaXplKGZpbHRlckRlcHRoLCBkaWxhdGlvbkRlcHRoKTtcbiAgY29uc3QgZWZmZWN0aXZlRmlsdGVySGVpZ2h0ID0gZ2V0RWZmZWN0aXZlRmlsdGVyU2l6ZShmaWx0ZXJIZWlnaHQsIGRpbGF0aW9uSGVpZ2h0KTtcbiAgY29uc3QgZWZmZWN0aXZlRmlsdGVyV2lkdGggPSBnZXRFZmZlY3RpdmVGaWx0ZXJTaXplKGZpbHRlcldpZHRoLCBkaWxhdGlvbldpZHRoKTtcbiAgY29uc3QgeyBwYWRJbmZvLCBvdXREZXB0aCwgb3V0SGVpZ2h0LCBvdXRXaWR0aCB9ID0gZ2V0M0RQYWRBbmRPdXRJbmZvKFxuICAgIHBhZCxcbiAgICBpbkRlcHRoLFxuICAgIGluSGVpZ2h0LFxuICAgIGluV2lkdGgsXG4gICAgc3RyaWRlRGVwdGgsXG4gICAgc3RyaWRlSGVpZ2h0LFxuICAgIHN0cmlkZVdpZHRoLFxuICAgIGVmZmVjdGl2ZUZpbHRlckRlcHRoLFxuICAgIGVmZmVjdGl2ZUZpbHRlckhlaWdodCxcbiAgICBlZmZlY3RpdmVGaWx0ZXJXaWR0aCxcbiAgKTtcblxuICBjb25zdCBvdXRDaGFubmVscyA9IGRlcHRod2lzZSA/IGZpbHRlckNoYW5uZWxzICogaW5DaGFubmVscyA6IGZpbHRlckNoYW5uZWxzO1xuXG4gIGxldCBvdXRTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9IFswLCAwLCAwLCAwLCAwXTtcbiAgaWYgKGRhdGFGb3JtYXQgPT09ICdjaGFubmVsc0ZpcnN0Jykge1xuICAgIG91dFNoYXBlID0gW2JhdGNoU2l6ZSwgb3V0Q2hhbm5lbHMsIG91dERlcHRoLCBvdXRIZWlnaHQsIG91dFdpZHRoXTtcbiAgfSBlbHNlIGlmIChkYXRhRm9ybWF0ID09PSAnY2hhbm5lbHNMYXN0Jykge1xuICAgIG91dFNoYXBlID0gW2JhdGNoU2l6ZSwgb3V0RGVwdGgsIG91dEhlaWdodCwgb3V0V2lkdGgsIG91dENoYW5uZWxzXTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgYmF0Y2hTaXplLFxuICAgIGRhdGFGb3JtYXQsXG4gICAgaW5EZXB0aCxcbiAgICBpbkhlaWdodCxcbiAgICBpbldpZHRoLFxuICAgIGluQ2hhbm5lbHMsXG4gICAgb3V0RGVwdGgsXG4gICAgb3V0SGVpZ2h0LFxuICAgIG91dFdpZHRoLFxuICAgIG91dENoYW5uZWxzLFxuICAgIHBhZEluZm8sXG4gICAgc3RyaWRlRGVwdGgsXG4gICAgc3RyaWRlSGVpZ2h0LFxuICAgIHN0cmlkZVdpZHRoLFxuICAgIGZpbHRlckRlcHRoLFxuICAgIGZpbHRlckhlaWdodCxcbiAgICBmaWx0ZXJXaWR0aCxcbiAgICBlZmZlY3RpdmVGaWx0ZXJEZXB0aCxcbiAgICBlZmZlY3RpdmVGaWx0ZXJIZWlnaHQsXG4gICAgZWZmZWN0aXZlRmlsdGVyV2lkdGgsXG4gICAgZGlsYXRpb25EZXB0aCxcbiAgICBkaWxhdGlvbkhlaWdodCxcbiAgICBkaWxhdGlvbldpZHRoLFxuICAgIGluU2hhcGUsXG4gICAgb3V0U2hhcGUsXG4gICAgZmlsdGVyU2hhcGUsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlQ29udjNETmFpdmVQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzLFxuICBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGZpbHRlckRpbXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICBwYWRzOiByZWFkb25seSBudW1iZXJbXSxcbiAgZGF0YUZvcm1hdDogc3RyaW5nLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBpc0NoYW5uZWxMYXN0ID0gZGF0YUZvcm1hdCA9PT0gJ2NoYW5uZWxzTGFzdCc7XG4gIGNvbnN0IGluQ2hhbm5lbHMgPSBpc0NoYW5uZWxMYXN0ID8gaW5wdXRzWzBdLmRpbXNbM10gOiBpbnB1dHNbMF0uZGltc1sxXTtcbiAgLy8gVE9ETzogZW5hYmxlIHZlYzQuXG4gIGNvbnN0IGlzVmVjNCA9IGZhbHNlO1xuICBjb25zdCB3b3JrR3JvdXBTaXplOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPSBbNjQsIDEsIDFdO1xuICBjb25zdCBkaXNwYXRjaExheW91dCA9IHsgeDogb3V0cHV0U2hhcGUubWFwKChfLCBpKSA9PiBpKSB9O1xuICBjb25zdCBkaXNwYXRjaCA9IFtNYXRoLmNlaWwoYXJyYXlQcm9kdWN0KGRpc3BhdGNoTGF5b3V0LngubWFwKChkKSA9PiBvdXRwdXRTaGFwZVtkXSkpIC8gd29ya0dyb3VwU2l6ZVswXSksIDEsIDFdO1xuXG4gIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbY29udjNkX25haXZlX3dlYmdwdV0gZGlzcGF0Y2ggPSAke2Rpc3BhdGNofWApO1xuXG4gIGNvbnN0IGlubmVyRWxlbWVudFNpemUgPSBpc1ZlYzQgPyAoaXNDaGFubmVsTGFzdCAmJiBpbkNoYW5uZWxzICUgNCAhPT0gMCA/IDMgOiA0KSA6IDE7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBmaWx0ZXJEaW1zIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBhZHMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYXR0cmlidXRlcy5zdHJpZGVzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGF0dHJpYnV0ZXMuZGlsYXRpb25zIH0sXG4gIF07XG4gIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3Jtc0RhdGEoYXR0cmlidXRlcywgcHJvZ3JhbVVuaWZvcm1zKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzBdLmRpbXMsIGlucHV0c1sxXS5kaW1zKSk7XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWydyYW5rJywgJ3JhbmsnXTtcbiAgY29uc3QgaGFzQmlhcyA9IGlucHV0cy5sZW5ndGggPT09IDM7XG4gIGlmIChoYXNCaWFzKSB7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzJdLmRpbXMpKTtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCdyYW5rJyk7XG4gIH1cbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0cHV0U2hhcGUpKTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdmaWx0ZXJfZGltcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGZpbHRlckRpbXMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdwYWRzJywgdHlwZTogJ3UzMicsIGxlbmd0aDogcGFkcy5sZW5ndGggfSxcbiAgICAgIHsgbmFtZTogJ3N0cmlkZXMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBhdHRyaWJ1dGVzLnN0cmlkZXMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdkaWxhdGlvbnMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBhdHRyaWJ1dGVzLmRpbGF0aW9ucy5sZW5ndGggfSxcbiAgICBdO1xuICAgIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3JtcyhhdHRyaWJ1dGVzLCB1bmlmb3Jtcyk7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBjb21wb25lbnQgMiwgMy5cbiAgICBjb25zdCBjb21wb25lbnRzID0gaXNWZWM0ID8gNCA6IDE7XG4gICAgY29uc3QgdCA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShpbnB1dHNbMF0uZGF0YVR5cGUpO1xuXG4gICAgY29uc3QgeCA9IGlucHV0VmFyaWFibGUoXG4gICAgICAneCcsXG4gICAgICBpbnB1dHNbMF0uZGF0YVR5cGUsXG4gICAgICBpbnB1dHNbMF0uZGltcy5sZW5ndGgsXG4gICAgICBpbm5lckVsZW1lbnRTaXplID09PSAzID8gMSA6IGlubmVyRWxlbWVudFNpemUsXG4gICAgKTtcbiAgICBjb25zdCB3ID0gaW5wdXRWYXJpYWJsZSgnVycsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBpbnB1dFZhcmlhYmxlcyA9IFt4LCB3XTtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgncmVzdWx0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGxldCBkZWNsYXJlRnVuY3Rpb25zID0gJyc7XG4gICAgaWYgKGhhc0JpYXMpIHtcbiAgICAgIGNvbnN0IGJpYXMgPSBpbnB1dFZhcmlhYmxlKCdiaWFzJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBpbnB1dHNbMl0uZGltcy5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgICAgaW5wdXRWYXJpYWJsZXMucHVzaChiaWFzKTtcbiAgICAgIGRlY2xhcmVGdW5jdGlvbnMgKz0gYFxuICAgICAgICBmbiBnZXRCaWFzQnlPdXRwdXRDb29yZHMoY29vcmRzIDogYXJyYXk8dTMyLCA1PikgLT4gJHtpc1ZlYzQgPyBgdmVjNDwke3R9PmAgOiB0fSB7XG4gICAgICAgICAgcmV0dXJuIGJpYXNbJHtpc0NoYW5uZWxMYXN0ID8gZ2V0RWxlbWVudEF0KCdjb29yZHMnLCA0LCA1KSA6IGdldEVsZW1lbnRBdCgnY29vcmRzJywgMSwgNSl9JHtcbiAgICAgICAgICAgIGlzVmVjNCA/ICcvIDQnIDogJydcbiAgICAgICAgICB9XTtcbiAgICAgICAgfWA7XG4gICAgfVxuICAgIGNvbnN0IHJlc1R5cGUgPSB0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplLCB0KTtcbiAgICBjb25zdCBhcHBseUFjdGl2YXRpb24gPSBnZXRBY3RpdmF0aW9uU25pcHBldChhdHRyaWJ1dGVzLCByZXNUeXBlLCB0KTtcblxuICAgIHJldHVybiBgXG4gICAgICAgICAgICAke2RlY2xhcmVGdW5jdGlvbnN9XG4gICAgICAgICAgICBmbiBnZXRYKGQwIDogdTMyLCBkMSA6IHUzMiwgZDIgOiB1MzIsIGQzIDogdTMyLCBkNCA6IHUzMikgLT4gZjMyIHtcbiAgICAgICAgICAgICAgbGV0IGFJbmRpY2VzID0gYXJyYXk8dTMyLCA1PihkMCwgZDEsIGQyLCBkMywgZDQpO1xuICAgICAgICAgICAgICByZXR1cm4gJHt4LmdldEJ5SW5kaWNlcygnYUluZGljZXMnKX07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmbiBnZXRXKGQwIDogdTMyLCBkMSA6IHUzMiwgZDIgOiB1MzIsIGQzIDogdTMyLCBkNCA6IHUzMikgLT4gZjMyIHtcbiAgICAgICAgICAgICAgbGV0IGFJbmRpY2VzID0gYXJyYXk8dTMyLCA1PihkMCwgZDEsIGQyLCBkMywgZDQpO1xuICAgICAgICAgICAgICByZXR1cm4gJHt3LmdldEJ5SW5kaWNlcygnYUluZGljZXMnKX07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcmlhYmxlcywgb3V0cHV0KX1cbiAgICAgICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuICAgICAgICAgICAgICBsZXQgY29vcmRzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgICAgICAgICAgICBsZXQgYmF0Y2ggPSAke2dldEVsZW1lbnRBdCgnY29vcmRzJywgMCwgeC5yYW5rKX07XG4gICAgICAgICAgICAgIGxldCBkMiA9ICR7XG4gICAgICAgICAgICAgICAgaXNDaGFubmVsTGFzdCA/IGdldEVsZW1lbnRBdCgnY29vcmRzJywgeC5yYW5rIC0gMSwgeC5yYW5rKSA6IGdldEVsZW1lbnRBdCgnY29vcmRzJywgMSwgeC5yYW5rKVxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBsZXQgeEZSQ0Nvcm5lciA9IHZlYzM8dTMyPigke1xuICAgICAgICAgICAgICAgIGlzQ2hhbm5lbExhc3QgPyBnZXRFbGVtZW50QXQoJ2Nvb3JkcycsIDEsIHgucmFuaykgOiBnZXRFbGVtZW50QXQoJ2Nvb3JkcycsIDIsIHgucmFuaylcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgJHtpc0NoYW5uZWxMYXN0ID8gZ2V0RWxlbWVudEF0KCdjb29yZHMnLCAyLCB4LnJhbmspIDogZ2V0RWxlbWVudEF0KCdjb29yZHMnLCAzLCB4LnJhbmspfSxcbiAgICAgICAgICAgICAgJHtcbiAgICAgICAgICAgICAgICBpc0NoYW5uZWxMYXN0ID8gZ2V0RWxlbWVudEF0KCdjb29yZHMnLCAzLCB4LnJhbmspIDogZ2V0RWxlbWVudEF0KCdjb29yZHMnLCA0LCB4LnJhbmspXG4gICAgICAgICAgICAgIH0pICogdW5pZm9ybXMuc3RyaWRlcyAtIHVuaWZvcm1zLnBhZHM7XG4gICAgICAgICAgICAgIGxldCB4RkNvcm5lciA9IHhGUkNDb3JuZXIueDtcbiAgICAgICAgICAgICAgbGV0IHhSQ29ybmVyID0geEZSQ0Nvcm5lci55O1xuICAgICAgICAgICAgICBsZXQgeENDb3JuZXIgPSB4RlJDQ29ybmVyLno7XG4gICAgICAgICAgICAgIGxldCB4U2hhcGVZID0gJHtcbiAgICAgICAgICAgICAgICBpc0NoYW5uZWxMYXN0XG4gICAgICAgICAgICAgICAgICA/IGdldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIDEsIHgucmFuaylcbiAgICAgICAgICAgICAgICAgIDogZ2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgMiwgeC5yYW5rKVxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBsZXQgeFNoYXBlWiA9ICR7XG4gICAgICAgICAgICAgICAgaXNDaGFubmVsTGFzdFxuICAgICAgICAgICAgICAgICAgPyBnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCAyLCB4LnJhbmspXG4gICAgICAgICAgICAgICAgICA6IGdldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIDMsIHgucmFuaylcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgbGV0IHhTaGFwZVcgPSAke1xuICAgICAgICAgICAgICAgIGlzQ2hhbm5lbExhc3RcbiAgICAgICAgICAgICAgICAgID8gZ2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgMywgeC5yYW5rKVxuICAgICAgICAgICAgICAgICAgOiBnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCA0LCB4LnJhbmspXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIGxldCB4U2hhcGVVID0gJHtcbiAgICAgICAgICAgICAgICBpc0NoYW5uZWxMYXN0XG4gICAgICAgICAgICAgICAgICA/IGdldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIDQsIHgucmFuaylcbiAgICAgICAgICAgICAgICAgIDogZ2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgMSwgeC5yYW5rKVxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBsZXQgaW5wdXREZXB0aE5lYXJlc3RWZWM0ID0gKHhTaGFwZVUgLyA0KSAqIDQ7XG4gICAgICAgICAgICAgIGxldCBpbnB1dERlcHRoVmVjNFJlbWFpbmRlciA9IHhTaGFwZVUgJSA0O1xuXG4gICAgICAgICAgICAgIHZhciB2YWx1ZSA9IDAuMDtcbiAgICAgICAgICAgICAgZm9yICh2YXIgd0YgPSAwdTsgd0YgPCB1bmlmb3Jtcy5maWx0ZXJfZGltc1swXTsgd0YrKykge1xuICAgICAgICAgICAgICAgIGxldCB4RiA9IHhGQ29ybmVyICsgd0YgKiB1bmlmb3Jtcy5kaWxhdGlvbnNbMF07XG4gICAgICAgICAgICAgICAgaWYgKHhGIDwgMCB8fCB4RiA+PSB4U2hhcGVZKSB7XG4gICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciB3UiA9IDB1OyB3UiA8IHVuaWZvcm1zLmZpbHRlcl9kaW1zWzFdOyB3UisrKSB7XG4gICAgICAgICAgICAgICAgICBsZXQgeFIgPSB4UkNvcm5lciArIHdSICogdW5pZm9ybXMuZGlsYXRpb25zWzFdO1xuICAgICAgICAgICAgICAgICAgaWYgKHhSIDwgMCB8fCB4UiA+PSB4U2hhcGVaKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICBmb3IgKHZhciB3QyA9IDB1OyB3QyA8IHVuaWZvcm1zLmZpbHRlcl9kaW1zWzJdOyB3QysrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB4QyA9IHhDQ29ybmVyICsgd0MgKiB1bmlmb3Jtcy5kaWxhdGlvbnNbMl07XG4gICAgICAgICAgICAgICAgICAgIGlmICh4QyA8IDAgfHwgeEMgPj0geFNoYXBlVykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgZDEgPSAwdTsgZDEgPCBpbnB1dERlcHRoTmVhcmVzdFZlYzQ7IGQxICs9IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAke1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNDaGFubmVsTGFzdFxuICAgICAgICAgICAgICAgICAgICAgICAgICA/IGBsZXQgeFZhbHVlcyA9IHZlYzQ8ZjMyPihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCB4RiwgeFIsIHhDLCBkMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgeEYsIHhSLCB4QywgZDEgKyAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCB4RiwgeFIsIHhDLCBkMSArIDIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIHhGLCB4UiwgeEMsIGQxICsgMykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgOiBgbGV0IHhWYWx1ZXMgPSB2ZWM0PGYzMj4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgZDEsIHhGLCB4UiwgeEMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIGQxICsgMSwgeEYsIHhSLCB4QyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgZDEgKyAyLCB4RiwgeFIsIHhDKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCBkMSArIDMsIHhGLCB4UiwgeEMpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCB3VmFsdWVzID0gdmVjNDxmMzI+KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0VyhkMiwgZDEsIHdGLCB3Uiwgd0MpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0VyhkMiwgZDEgKyAxLCB3Riwgd1IsIHdDKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFcoZDIsIGQxICsgMiwgd0YsIHdSLCB3QyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRXKGQyLCBkMSArIDMsIHdGLCB3Uiwgd0MpKTtcbiAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSArPSBkb3QoeFZhbHVlcywgd1ZhbHVlcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0RGVwdGhWZWM0UmVtYWluZGVyID09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICR7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlzQ2hhbm5lbExhc3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGB2YWx1ZSArPSBnZXRYKGJhdGNoLCB4RiwgeFIsIHhDLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICogZ2V0VyhkMiwgaW5wdXREZXB0aE5lYXJlc3RWZWM0LCB3Riwgd1IsIHdDKTtgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBgdmFsdWUgKz0gZ2V0WChiYXRjaCwgaW5wdXREZXB0aE5lYXJlc3RWZWM0LCB4RiwgeFIsIHhDKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAqIGdldFcoZDIsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCwgd0YsIHdSLCB3Qyk7YFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlucHV0RGVwdGhWZWM0UmVtYWluZGVyID09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAke1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNDaGFubmVsTGFzdFxuICAgICAgICAgICAgICAgICAgICAgICAgICA/IGBsZXQgeFZhbHVlcyA9IHZlYzI8ZjMyPihcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIHhGLCB4UiwgeEMsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCksXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCB4RiwgeFIsIHhDLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQgKyAxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgICAgICAgICAgICA6IGBsZXQgeFZhbHVlcyA9IHZlYzI8ZjMyPihcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCwgeEYsIHhSLCB4QyksXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQgKyAxLCB4RiwgeFIsIHhDKSk7XG4gICAgICAgICAgICAgICAgICAgIGBcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxldCB3VmFsdWVzID0gdmVjMjxmMzI+KFxuICAgICAgICAgICAgICAgICAgICAgIGdldFcoZDIsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCwgd0YsIHdSLCB3QyksXG4gICAgICAgICAgICAgICAgICAgICAgZ2V0VyhkMiwgaW5wdXREZXB0aE5lYXJlc3RWZWM0ICsgMSwgd0YsIHdSLCB3QykpO1xuICAgICAgICAgICAgICAgICAgICAgIHZhbHVlICs9IGRvdCh4VmFsdWVzLCB3VmFsdWVzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpbnB1dERlcHRoVmVjNFJlbWFpbmRlciA9PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgJHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzQ2hhbm5lbExhc3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPyBgbGV0IHhWYWx1ZXMgPSB2ZWMzPGYzMj4oXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCB4RiwgeFIsIHhDLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0WChiYXRjaCwgeEYsIHhSLCB4QywgaW5wdXREZXB0aE5lYXJlc3RWZWM0ICsgMSksXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCB4RiwgeFIsIHhDLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQgKyAyKSk7XG4gICAgICAgICAgICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgICAgICAgICAgICA6IGBsZXQgeFZhbHVlcyA9IHZlYzM8ZjMyPihcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCwgeEYsIHhSLCB4QyksXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRYKGJhdGNoLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQgKyAxLCB4RiwgeFIsIHhDKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldFgoYmF0Y2gsIGlucHV0RGVwdGhOZWFyZXN0VmVjNCArIDIsIHhGLCB4UiwgeEMpKTtcbiAgICAgICAgICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGV0IHdWYWx1ZXMgPSB2ZWMzPGYzMj4oXG4gICAgICAgICAgICAgICAgICAgICAgZ2V0VyhkMiwgaW5wdXREZXB0aE5lYXJlc3RWZWM0LCB3Riwgd1IsIHdDKSxcbiAgICAgICAgICAgICAgICAgICAgICBnZXRXKGQyLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQgKyAxLCB3Riwgd1IsIHdDKSxcbiAgICAgICAgICAgICAgICAgICAgICBnZXRXKGQyLCBpbnB1dERlcHRoTmVhcmVzdFZlYzQgKyAyLCB3Riwgd1IsIHdDKSk7XG4gICAgICAgICAgICAgICAgICAgICAgdmFsdWUgKz0gZG90KHhWYWx1ZXMsIHdWYWx1ZXMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICR7aGFzQmlhcyA/ICd2YWx1ZSA9IHZhbHVlICsgZ2V0Qmlhc0J5T3V0cHV0Q29vcmRzKGNvb3JkcyknIDogJyd9O1xuICAgICAgICAgICAgICAke2FwcGx5QWN0aXZhdGlvbn1cbiAgICAgICAgICAgICAgcmVzdWx0W2dsb2JhbF9pZHhdID0gZjMyKHZhbHVlKTtcbiAgICAgICAgICB9YDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQ29udjNETmFpdmUnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2F0dHJpYnV0ZXMuY2FjaGVLZXl9OyR7aXNDaGFubmVsTGFzdH07JHtpbm5lckVsZW1lbnRTaXplfTske2hhc0JpYXN9YCwgaW5wdXREZXBlbmRlbmNpZXMgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IGRpc3BhdGNoWzBdLCB5OiBkaXNwYXRjaFsxXSwgejogZGlzcGF0Y2hbMl0gfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IFByb2dyYW1JbmZvLCBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeSwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBnZXRNYXhDb21wb25lbnRzLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5pbXBvcnQgeyBDb252QXR0cmlidXRlcyB9IGZyb20gJy4vY29udic7XG5pbXBvcnQgeyBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXMsIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3Jtc0RhdGEsIGdldEFjdGl2YXRpb25TbmlwcGV0IH0gZnJvbSAnLi9mdXNlLXV0aWxzJztcblxuLyoqXG4gKiBuYWl2ZSBncm91cGVkIGNvbnYgaW1wbGVtZW50YXRpb24sIHN1cHBvcnRzIDFkLzJkIGNvbnZcbiAqIEBwYXJhbSBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbiAtIGFuIG9wdGlvbmFsIGZ1bmN0aW9uIHRvIHNxdWVlemUgdGhlIG91dHB1dCBzaGFwZSwgb25seSB1c2VkIGluIGNvbnYxZFxuICovXG5leHBvcnQgY29uc3QgY3JlYXRlR3JvdXBlZENvbnZQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzLFxuICBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uPzogKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSkgPT4gbnVtYmVyW10sXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGhhc0JpYXMgPSBpbnB1dHMubGVuZ3RoID4gMjtcbiAgY29uc3QgcHJvY2Vzc0JpYXMgPSBoYXNCaWFzID8gJ3ZhbHVlICs9IGJbb3V0cHV0X2NoYW5uZWxdOycgOiAnJztcbiAgY29uc3QgeFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IHdTaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuXG4gIGNvbnN0IGlzQ2hhbm5lbExhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuICBjb25zdCBvdXRwdXRDaGFubmVscyA9IGlzQ2hhbm5lbExhc3QgPyBvdXRwdXRTaGFwZVszXSA6IG91dHB1dFNoYXBlWzFdO1xuICBjb25zdCBvdXRwdXRDaGFubmVsc1Blckdyb3VwID0gb3V0cHV0Q2hhbm5lbHMgLyBhdHRyaWJ1dGVzLmdyb3VwO1xuICBjb25zdCBjb21wb25lbnRzID0gaXNDaGFubmVsTGFzdCAmJiBvdXRwdXRDaGFubmVsc1Blckdyb3VwID49IDQgPyBnZXRNYXhDb21wb25lbnRzKG91dHB1dENoYW5uZWxzKSA6IDE7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyBjb21wb25lbnRzO1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBhdHRyaWJ1dGVzLmRpbGF0aW9ucyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBbYXR0cmlidXRlcy5zdHJpZGVzWzBdLCBhdHRyaWJ1dGVzLnN0cmlkZXNbMV1dIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IFthdHRyaWJ1dGVzLnBhZHNbMF0sIGF0dHJpYnV0ZXMucGFkc1sxXV0gfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0Q2hhbm5lbHNQZXJHcm91cCB9LFxuICBdO1xuICBhcHBlbmRBY3RpdmF0aW9uVW5pZm9ybXNEYXRhKGF0dHJpYnV0ZXMsIHByb2dyYW1Vbmlmb3Jtcyk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKFxuICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKHhTaGFwZSwgW3dTaGFwZVswXSwgd1NoYXBlWzFdLCB3U2hhcGVbMl0sIHdTaGFwZVszXSAvIGNvbXBvbmVudHNdKSxcbiAgKTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBoYXNCaWFzID8gWydyYW5rJywgJ3JhbmsnLCAncmFuayddIDogWydyYW5rJywgJ3JhbmsnXTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goXG4gICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoW291dHB1dFNoYXBlWzBdLCBvdXRwdXRTaGFwZVsxXSwgb3V0cHV0U2hhcGVbMl0sIG91dHB1dFNoYXBlWzNdIC8gY29tcG9uZW50c10pLFxuICApO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3QgYmFzZVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUob3V0cHV0LnR5cGUudGVuc29yKTtcbiAgICBjb25zdCBhcHBseUFjdGl2YXRpb24gPSBnZXRBY3RpdmF0aW9uU25pcHBldChhdHRyaWJ1dGVzLCBvdXRwdXQudHlwZS52YWx1ZSwgYmFzZVR5cGUpO1xuICAgIGNvbnN0IHggPSBpbnB1dFZhcmlhYmxlKCd4JywgaW5wdXRzWzBdLmRhdGFUeXBlLCB4U2hhcGUubGVuZ3RoKTtcbiAgICBjb25zdCB3ID0gaW5wdXRWYXJpYWJsZSgndycsIGlucHV0c1sxXS5kYXRhVHlwZSwgd1NoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3QgaW5wdXRWYXJzID0gW3gsIHddO1xuICAgIGlmIChoYXNCaWFzKSB7XG4gICAgICBpbnB1dFZhcnMucHVzaChpbnB1dFZhcmlhYmxlKCdiJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBpbnB1dHNbMl0uZGltcywgY29tcG9uZW50cykpO1xuICAgIH1cblxuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ291dHB1dF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2RpbGF0aW9ucycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGF0dHJpYnV0ZXMuZGlsYXRpb25zLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAnc3RyaWRlcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IDIgfSxcbiAgICAgIHsgbmFtZTogJ3BhZHMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiAyIH0sXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfY2hhbm5lbHNfcGVyX2dyb3VwJywgdHlwZTogJ3UzMicgfSxcbiAgICBdO1xuICAgIGFwcGVuZEFjdGl2YXRpb25Vbmlmb3JtcyhhdHRyaWJ1dGVzLCB1bmlmb3Jtcyk7XG5cbiAgICBjb25zdCBjYWxjdWxhdGVSZXN1bHQgPSBpc0NoYW5uZWxMYXN0XG4gICAgICA/IGBcbiAgICAgIGZvciAodmFyIHdIZWlnaHQ6IHUzMiA9IDB1OyB3SGVpZ2h0IDwgdW5pZm9ybXMud19zaGFwZVswXTsgd0hlaWdodCsrKSB7XG4gICAgICAgIGxldCB4SGVpZ2h0ID0geFJDQ29ybmVyLnggKyB3SGVpZ2h0ICogdW5pZm9ybXMuZGlsYXRpb25zWzBdO1xuXG4gICAgICAgIGlmICh4SGVpZ2h0IDwgMHUgfHwgeEhlaWdodCA+PSB1bmlmb3Jtcy54X3NoYXBlWzFdKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciB3V2lkdGg6IHUzMiA9IDB1OyB3V2lkdGggPCB1bmlmb3Jtcy53X3NoYXBlWzFdOyB3V2lkdGgrKykge1xuICAgICAgICAgIGxldCB4V2lkdGggPSB4UkNDb3JuZXIueSArIHdXaWR0aCAqIHVuaWZvcm1zLmRpbGF0aW9uc1sxXTtcbiAgICAgICAgICBpZiAoeFdpZHRoIDwgMHUgfHwgeFdpZHRoID49IHVuaWZvcm1zLnhfc2hhcGVbMl0pIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGZvciAodmFyIHdJbkNoYW5uZWw6IHUzMiA9IDB1OyB3SW5DaGFubmVsIDwgdW5pZm9ybXMud19zaGFwZVsyXTsgd0luQ2hhbm5lbCsrKSB7XG4gICAgICAgICAgICBsZXQgaW5wdXRfY2hhbm5lbCA9IGluX2NoYW5uZWxfb2Zmc2V0ICsgd0luQ2hhbm5lbDtcbiAgICAgICAgICAgIGxldCB4VmFsID0gJHt4LmdldCgnYmF0Y2gnLCAneEhlaWdodCcsICd4V2lkdGgnLCAnaW5wdXRfY2hhbm5lbCcpfTtcbiAgICAgICAgICAgIGxldCB3VmFsID0gJHt3LmdldCgnd0hlaWdodCcsICd3V2lkdGgnLCAnd0luQ2hhbm5lbCcsICdvdXRwdXRfY2hhbm5lbCcpfTtcbiAgICAgICAgICAgIHZhbHVlICs9IHhWYWwgKiB3VmFsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYFxuICAgICAgOiBgXG4gICAgICBmb3IgKHZhciB3SW5DaGFubmVsOiB1MzIgPSAwdTsgd0luQ2hhbm5lbCA8IHVuaWZvcm1zLndfc2hhcGVbMV07IHdJbkNoYW5uZWwrKykge1xuICAgICAgICBsZXQgaW5wdXRfY2hhbm5lbCA9IGluX2NoYW5uZWxfb2Zmc2V0ICsgd0luQ2hhbm5lbDtcbiAgICAgICAgZm9yICh2YXIgd0hlaWdodDogdTMyID0gMHU7IHdIZWlnaHQgPCB1bmlmb3Jtcy53X3NoYXBlWzJdOyB3SGVpZ2h0KyspIHtcbiAgICAgICAgICBsZXQgeEhlaWdodCA9IHhSQ0Nvcm5lci54ICsgd0hlaWdodCAqIHVuaWZvcm1zLmRpbGF0aW9uc1swXTtcblxuICAgICAgICAgIGlmICh4SGVpZ2h0IDwgMHUgfHwgeEhlaWdodCA+PSB1bmlmb3Jtcy54X3NoYXBlWzJdKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmb3IgKHZhciB3V2lkdGg6IHUzMiA9IDB1OyB3V2lkdGggPCB1bmlmb3Jtcy53X3NoYXBlWzNdOyB3V2lkdGgrKykge1xuICAgICAgICAgICAgbGV0IHhXaWR0aCA9IHhSQ0Nvcm5lci55ICsgd1dpZHRoICogdW5pZm9ybXMuZGlsYXRpb25zWzFdO1xuICAgICAgICAgICAgaWYgKHhXaWR0aCA8IDB1IHx8IHhXaWR0aCA+PSB1bmlmb3Jtcy54X3NoYXBlWzNdKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgeFZhbCA9ICR7eC5nZXQoJ2JhdGNoJywgJ2lucHV0X2NoYW5uZWwnLCAneEhlaWdodCcsICd4V2lkdGgnKX07XG4gICAgICAgICAgICBsZXQgd1ZhbCA9ICR7dy5nZXQoJ291dHB1dF9jaGFubmVsJywgJ3dJbkNoYW5uZWwnLCAnd0hlaWdodCcsICd3V2lkdGgnKX07XG4gICAgICAgICAgICB2YWx1ZSArPSB4VmFsICogd1ZhbDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGA7XG4gICAgcmV0dXJuIGBcbiAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcnMsIG91dHB1dCl9XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cblxuICAgIGxldCBvdXRwdXRJbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgIGxldCBiYXRjaDogdTMyID0gb3V0cHV0SW5kaWNlc1swXTtcbiAgICBsZXQgb3V0cHV0X2NoYW5uZWw6IHUzMiA9IG91dHB1dEluZGljZXNbJHtpc0NoYW5uZWxMYXN0ID8gMyA6IDF9XTtcbiAgICBsZXQgeFJDQ29ybmVyOiB2ZWMyPHUzMj4gPSB2ZWMyPHUzMj4ob3V0cHV0SW5kaWNlc1ske2lzQ2hhbm5lbExhc3QgPyAxIDogMn1dLCBvdXRwdXRJbmRpY2VzWyR7XG4gICAgICBpc0NoYW5uZWxMYXN0ID8gMiA6IDNcbiAgICB9XSkgKiB1bmlmb3Jtcy5zdHJpZGVzIC0gdW5pZm9ybXMucGFkcztcbiAgICBsZXQgZ3JvdXBfaWQ6IHUzMiA9IG91dHB1dF9jaGFubmVsICogJHtjb21wb25lbnRzfSAvIHVuaWZvcm1zLm91dHB1dF9jaGFubmVsc19wZXJfZ3JvdXA7XG4gICAgdmFyIGluX2NoYW5uZWxfb2Zmc2V0ID0gZ3JvdXBfaWQgKiB1bmlmb3Jtcy53X3NoYXBlWyR7aXNDaGFubmVsTGFzdCA/IDIgOiAxfV07XG5cbiAgICB2YXIgdmFsdWU6ICR7b3V0cHV0LnR5cGUudmFsdWV9ID0gJHtvdXRwdXQudHlwZS52YWx1ZX0oMCk7XG4gICAgJHtjYWxjdWxhdGVSZXN1bHR9XG4gICAgJHtwcm9jZXNzQmlhc31cbiAgICAke2FwcGx5QWN0aXZhdGlvbn1cbiAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICd2YWx1ZScpfVxuICB9YDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnR3JvdXBlZENvbnYnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2F0dHJpYnV0ZXMuY2FjaGVLZXl9XyR7Y29tcG9uZW50c31gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBkaW1zOiBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbiA/IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uKG91dHB1dFNoYXBlKSA6IG91dHB1dFNoYXBlLFxuICAgICAgICAgIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVHcm91cGVkQ29udlZlY3Rvcml6ZVByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMsXG4gIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24/OiAoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKSA9PiBudW1iZXJbXSxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaGFzQmlhcyA9IGlucHV0cy5sZW5ndGggPiAyO1xuICBjb25zdCBjb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhvdXRwdXRTaGFwZVszXSk7XG4gIGNvbnN0IG91dHB1dE51bWJlciA9IGdldE1heENvbXBvbmVudHMob3V0cHV0U2hhcGVbMl0pO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gY29tcG9uZW50cyAvIG91dHB1dE51bWJlcjtcbiAgY29uc3QgeFNoYXBlID0gW2lucHV0c1swXS5kaW1zWzBdLCBpbnB1dHNbMF0uZGltc1sxXSwgaW5wdXRzWzBdLmRpbXNbMl0sIGlucHV0c1swXS5kaW1zWzNdIC8gY29tcG9uZW50c107XG4gIGNvbnN0IHdTaGFwZSA9IFtpbnB1dHNbMV0uZGltc1swXSwgaW5wdXRzWzFdLmRpbXNbMV0sIGlucHV0c1sxXS5kaW1zWzJdLCBpbnB1dHNbMV0uZGltc1szXSAvIGNvbXBvbmVudHNdO1xuICBjb25zdCBvdXRwdXRTaGFwZUluU2hhZGVyID0gW291dHB1dFNoYXBlWzBdLCBvdXRwdXRTaGFwZVsxXSwgb3V0cHV0U2hhcGVbMl0sIG91dHB1dFNoYXBlWzNdIC8gY29tcG9uZW50c107XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogW2F0dHJpYnV0ZXMuc3RyaWRlc1swXSwgYXR0cmlidXRlcy5zdHJpZGVzWzFdXSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuaW50MzIsIGRhdGE6IFthdHRyaWJ1dGVzLnBhZHNbMF0sIGF0dHJpYnV0ZXMucGFkc1sxXV0gfSxcbiAgXTtcbiAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zRGF0YShhdHRyaWJ1dGVzLCBwcm9ncmFtVW5pZm9ybXMpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyh4U2hhcGUsIHdTaGFwZSwgb3V0cHV0U2hhcGVJblNoYWRlcikpO1xuICBjb25zdCB4TnVtYmVyID0gKG91dHB1dE51bWJlciAtIDEpICogYXR0cmlidXRlcy5zdHJpZGVzWzFdICsgd1NoYXBlWzFdO1xuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZUluU2hhZGVyLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3QgYmFzZVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUob3V0cHV0LnR5cGUudGVuc29yKTtcbiAgICBjb25zdCBhcHBseUFjdGl2YXRpb24gPSBnZXRBY3RpdmF0aW9uU25pcHBldChhdHRyaWJ1dGVzLCBvdXRwdXQudHlwZS52YWx1ZSwgYmFzZVR5cGUpO1xuICAgIGNvbnN0IHggPSBpbnB1dFZhcmlhYmxlKCd4JywgaW5wdXRzWzBdLmRhdGFUeXBlLCB4U2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCB3ID0gaW5wdXRWYXJpYWJsZSgndycsIGlucHV0c1sxXS5kYXRhVHlwZSwgd1NoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3QgaW5wdXRWYXJzID0gW3gsIHddO1xuICAgIGlmIChoYXNCaWFzKSB7XG4gICAgICBpbnB1dFZhcnMucHVzaChpbnB1dFZhcmlhYmxlKCdiJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBpbnB1dHNbMl0uZGltcywgY29tcG9uZW50cykpO1xuICAgIH1cbiAgICBjb25zdCBwcm9jZXNzQmlhcyA9IGhhc0JpYXMgPyAndmFsdWUgKz0gYltvdXRwdXRfY2hhbm5lbF07JyA6ICcnO1xuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ291dHB1dF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3N0cmlkZXMnLCB0eXBlOiAnaTMyJywgbGVuZ3RoOiAyIH0sXG4gICAgICB7IG5hbWU6ICdwYWRzJywgdHlwZTogJ2kzMicsIGxlbmd0aDogMiB9LFxuICAgIF07XG4gICAgYXBwZW5kQWN0aXZhdGlvblVuaWZvcm1zKGF0dHJpYnV0ZXMsIHVuaWZvcm1zKTtcbiAgICByZXR1cm4gYFxuICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKC4uLmlucHV0VmFycywgb3V0cHV0KX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cbiAgICBsZXQgd2lkdGgwID0gdW5pZm9ybXMub3V0cHV0X3NoYXBlWzNdO1xuICAgIGxldCBvdXRwdXRfY2hhbm5lbCA9IGdsb2JhbF9pZHggJSB3aWR0aDA7XG4gICAgdmFyIGluZGV4MSA9IGdsb2JhbF9pZHggLyB3aWR0aDA7XG4gICAgbGV0IHdpZHRoMSA9IHVuaWZvcm1zLm91dHB1dF9zaGFwZVsyXSAvICR7b3V0cHV0TnVtYmVyfXU7XG4gICAgbGV0IGNvbCA9IChpbmRleDEgJSB3aWR0aDEpICogJHtvdXRwdXROdW1iZXJ9dTtcbiAgICBpbmRleDEgPSBpbmRleDEgLyB3aWR0aDE7XG4gICAgbGV0IHJvdyA9IGluZGV4MSAlIHVuaWZvcm1zLm91dHB1dF9zaGFwZVsxXTtcbiAgICBsZXQgYmF0Y2ggPSBpbmRleDEgLyB1bmlmb3Jtcy5vdXRwdXRfc2hhcGVbMV07XG5cbiAgICBsZXQgeF9jb3JuZXIgPSB2ZWMyPGkzMj4oaTMyKHJvdyksIGkzMihjb2wpKSAqIHVuaWZvcm1zLnN0cmlkZXMgLSB1bmlmb3Jtcy5wYWRzO1xuXG4gICAgdmFyIHhfdmFsczogYXJyYXk8JHt4LnR5cGUudmFsdWV9LCAke3hOdW1iZXJ9PjtcbiAgICB2YXIgdmFsdWVzOiBhcnJheTwke291dHB1dC50eXBlLnZhbHVlfSwgJHtvdXRwdXROdW1iZXJ9PjtcbiAgICBsZXQgaW5wdXRfY2hhbm5lbCA9IG91dHB1dF9jaGFubmVsO1xuICAgIC8vIFVzZSBjb25zdGFudCBpbnN0ZWFkIG9mIHVuaWZvcm0gY2FuIGdpdmUgYmV0dGVyIHBlcmZvcm1hbmNlIGZvciB3J3MgaGVpZ2h0L3dpZHRoLlxuICAgIGZvciAodmFyIHdfaGVpZ2h0OiB1MzIgPSAwdTsgd19oZWlnaHQgPCAke3dTaGFwZVswXX07IHdfaGVpZ2h0KyspIHtcbiAgICAgIGxldCB4X2hlaWdodCA9IHhfY29ybmVyLnggKyBpMzIod19oZWlnaHQpO1xuICAgICAgaWYgKHhfaGVpZ2h0ID49IDAgJiYgdTMyKHhfaGVpZ2h0KSA8IHVuaWZvcm1zLnhfc2hhcGVbMV0pIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAke3hOdW1iZXJ9OyBpKyspIHtcbiAgICAgICAgICBsZXQgeF93aWR0aCA9IHhfY29ybmVyLnkgKyBpO1xuICAgICAgICAgIGlmICh4X3dpZHRoID49IDAgJiYgdTMyKHhfd2lkdGgpIDwgdW5pZm9ybXMueF9zaGFwZVsyXSkge1xuICAgICAgICAgICAgeF92YWxzW2ldID0gJHt4LmdldCgnYmF0Y2gnLCAndTMyKHhfaGVpZ2h0KScsICd1MzIoeF93aWR0aCknLCAnaW5wdXRfY2hhbm5lbCcpfTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgeF92YWxzW2ldID0gJHt4LnR5cGUudmFsdWV9KDApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciB3X3dpZHRoOiB1MzIgPSAwdTsgd193aWR0aCA8ICR7d1NoYXBlWzFdfTsgd193aWR0aCsrKSB7XG4gICAgICAgICAgbGV0IHdfdmFsID0gJHt3LmdldCgnd19oZWlnaHQnLCAnd193aWR0aCcsICcwJywgJ291dHB1dF9jaGFubmVsJyl9O1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwdTsgaSA8ICR7b3V0cHV0TnVtYmVyfXU7IGkrKykge1xuICAgICAgICAgICAgdmFsdWVzW2ldID0gZm1hKHhfdmFsc1tpICogdTMyKHVuaWZvcm1zLnN0cmlkZXNbMV0pICsgd193aWR0aF0sIHdfdmFsLCB2YWx1ZXNbaV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwdTsgaSA8ICR7b3V0cHV0TnVtYmVyfXU7IGkrKykge1xuICAgICAgdmFyIHZhbHVlID0gdmFsdWVzW2ldO1xuICAgICAgJHtwcm9jZXNzQmlhc31cbiAgICAgICR7YXBwbHlBY3RpdmF0aW9ufVxuICAgICAgJHtvdXRwdXQuc2V0KCdiYXRjaCcsICdyb3cnLCAnY29sICsgaScsICdvdXRwdXRfY2hhbm5lbCcsICd2YWx1ZScpfTtcbiAgICB9XG4gIH1gO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0dyb3VwZWRDb252LVZlY3Rvcml6ZScsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2F0dHJpYnV0ZXMuY2FjaGVLZXl9OyR7Y29tcG9uZW50c307JHtvdXRwdXROdW1iZXJ9OyR7eE51bWJlcn07JHt3U2hhcGVbMF19OyR7d1NoYXBlWzFdfWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llczogaGFzQmlhcyA/IFsncmFuaycsICdyYW5rJywgJ3R5cGUnXSA6IFsncmFuaycsICdyYW5rJ10sXG4gICAgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW1xuICAgICAgICB7XG4gICAgICAgICAgZGltczogc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24gPyBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbihvdXRwdXRTaGFwZSkgOiBvdXRwdXRTaGFwZSxcbiAgICAgICAgICBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgUG9vbENvbnZVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQgfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZUNvbnYyRE1hdE11bFByb2dyYW1JbmZvIH0gZnJvbSAnLi8zcmQtcGFydHkvY29udjJkX21tX3dlYmdwdSc7XG5pbXBvcnQgeyBjb21wdXRlQ29udjNESW5mbywgY3JlYXRlQ29udjNETmFpdmVQcm9ncmFtSW5mbyB9IGZyb20gJy4vM3JkLXBhcnR5L2NvbnYzZF9uYWl2ZV93ZWJncHUnO1xuaW1wb3J0IHsgY3JlYXRlTWF0bXVsUHJvZ3JhbUluZm8gfSBmcm9tICcuLzNyZC1wYXJ0eS9tYXRtdWxfcGFja2VkX3dlYmdwdSc7XG5pbXBvcnQgeyBjcmVhdGVHcm91cGVkQ29udlByb2dyYW1JbmZvLCBjcmVhdGVHcm91cGVkQ29udlZlY3Rvcml6ZVByb2dyYW1JbmZvIH0gZnJvbSAnLi9jb252LWdyb3VwZWQnO1xuaW1wb3J0IHsgSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcywgcGFyc2VJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzIH0gZnJvbSAnLi9mdXNlLXV0aWxzJztcbmltcG9ydCB7IGNyZWF0ZU5haXZlTWF0bXVsUHJvZ3JhbUluZm8gfSBmcm9tICcuL21hdG11bC1zaGFkZXJzJztcbmltcG9ydCB7IGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvIH0gZnJvbSAnLi90cmFuc3Bvc2UnO1xuXG5leHBvcnQgY29uc3QgY2FsY3VsYXRlT3V0cHV0U2hhcGUgPSAoXG4gIGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGRpbGF0aW9uczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGFkanVzdFBhZHM6IHJlYWRvbmx5IG51bWJlcltdLFxuICBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXSxcbiAgaXNDaGFubmVsTGFzdDogYm9vbGVhbixcbik6IG51bWJlcltdID0+IHtcbiAgY29uc3QgYmF0Y2hTaXplID0gaW5wdXRTaGFwZVswXTtcbiAgY29uc3QgaW5wdXRTcGF0aWFsU2hhcGUgPSBpbnB1dFNoYXBlLnNsaWNlKGlzQ2hhbm5lbExhc3QgPyAxIDogMiwgaXNDaGFubmVsTGFzdCA/IDMgOiA0KTtcbiAgY29uc3Qgc3BhdGlhbFJhbmsgPSBpbnB1dFNwYXRpYWxTaGFwZS5sZW5ndGg7XG4gIGNvbnN0IG91dENoYW5uZWxzID0ga2VybmVsU2hhcGVbMF07XG4gIGNvbnN0IGtlcm5lbFNwYXRpYWxTaGFwZSA9IGtlcm5lbFNoYXBlLnNsaWNlKDIpO1xuICBjb25zdCBkaWxhdGVkS2VybmVsU2hhcGUgPSBrZXJuZWxTcGF0aWFsU2hhcGUubWFwKCh2LCBpKSA9PiB2ICsgKHYgLSAxKSAqIChkaWxhdGlvbnNbaV0gLSAxKSk7XG4gIGNvbnN0IGlucHV0U3BhdGlhbFNoYXBlV2l0aFBhZCA9IGlucHV0U3BhdGlhbFNoYXBlLm1hcCgodiwgaSkgPT4gdiArIGFkanVzdFBhZHNbaV0gKyBhZGp1c3RQYWRzW2kgKyBzcGF0aWFsUmFua10pO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGlucHV0U3BhdGlhbFNoYXBlV2l0aFBhZC5tYXAoKHYsIGkpID0+XG4gICAgTWF0aC5mbG9vcigodiAtIGRpbGF0ZWRLZXJuZWxTaGFwZVtpXSArIHN0cmlkZXNbaV0pIC8gc3RyaWRlc1tpXSksXG4gICk7XG4gIG91dHB1dFNoYXBlLnNwbGljZSgwLCAwLCBiYXRjaFNpemUpO1xuICBvdXRwdXRTaGFwZS5zcGxpY2UoaXNDaGFubmVsTGFzdCA/IDMgOiAxLCAwLCBvdXRDaGFubmVscyk7XG4gIHJldHVybiBvdXRwdXRTaGFwZTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udkF0dHJpYnV0ZXMgZXh0ZW5kcyBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzLCBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBhdXRvUGFkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGRpbGF0aW9uczogcmVhZG9ubHkgbnVtYmVyW107XG4gIHJlYWRvbmx5IGZvcm1hdDogJ05IV0MnIHwgJ05DSFcnO1xuICByZWFkb25seSBncm91cDogbnVtYmVyO1xuICByZWFkb25seSBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW107XG4gIHJlYWRvbmx5IHBhZHM6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgd0lzQ29uc3Q6IGJvb2xlYW47XG59XG5cbi8vIGZvciB0cmFuc3Bvc2luZyB3ZWlnaHQgdGVuc29yIGZyb20gW00sIEMvZ3JvdXAsIEtILCBLV10gdG8gW0tILCBLVywgQy9ncm91cCwgTV1cbmNvbnN0IHdlaWdodFRyYW5zcG9zZUF0dHJpYnV0ZSA9IFsyLCAzLCAxLCAwXTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIC8vIFJlZmVyIHRvIHRoZSBiZWxvdyBsaW5rIGZvciBhbGwgaW5wdXQgY2hlY2tzXG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9vbm54L29ubngvYmxvYi9tYXN0ZXIvZG9jcy9PcGVyYXRvcnMubWQjQ29udlxuICBpZiAoIWlucHV0cyB8fCAoaW5wdXRzLmxlbmd0aCAhPT0gMiAmJiBpbnB1dHMubGVuZ3RoICE9PSAzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ29udiByZXF1aXJlcyAyIG9yIDMgaW5wdXRzJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoID4gNSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZ3JlYXRlciB0aGFuIDVEIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IGlucHV0c1sxXS5kaW1zLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignZmlsdGVyIGRvZXMgbm90IGhhdmUgc2FtZSBkaW1lbnNpb24gYXMgaW5wdXQnKTtcbiAgfVxuXG4gIC8vIEZJTFRFUl9JTl9DSEFOTkVMIHNob3VsZCBiZSBlcXVhbCB0byBEQVRBX0NIQU5ORUxcbiAgY29uc3QgZGF0YUNoYW5uZWwgPSBpbnB1dHNbMF0uZGltc1thdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnID8gaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMSA6IDFdO1xuICBjb25zdCBmaWx0ZXJJbkNoYW5uZWwgPSBpbnB1dHNbMV0uZGltc1sxXSAqIGF0dHJpYnV0ZXMuZ3JvdXA7XG4gIGlmIChkYXRhQ2hhbm5lbCAhPT0gZmlsdGVySW5DaGFubmVsKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGSUxURVJfSU5fQ0hBTk5FTCBzaG91bGQgYmUgZXF1YWwgdG8gREFUQV9DSEFOTkVMJyk7XG4gIH1cblxuICAvLyBpZiBiaWFzIGlzIHByb3ZpZGVkIGl0IHNob3VsZCBiZSAxRCBhbmQgdGhlIG51bWJlciBvZiBlbGVtZW50cyBzaG91bGQgYmUgZXF1YWwgdG8gdGhlIG51bWJlciBvZiBmZWF0dXJlIG1hcHNcbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMgJiYgKGlucHV0c1syXS5kaW1zLmxlbmd0aCAhPT0gMSB8fCBpbnB1dHNbMV0uZGltc1swXSAhPT0gaW5wdXRzWzJdLmRpbXNbMF0pKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGJpYXMnKTtcbiAgfVxuXG4gIGNvbnN0IHNwYXRpYWxSYW5rID0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMjtcbiAgLy8gd3JvbmcgZGlsYXRpb25zIGRpbWVuc2lvblxuICBpZiAoYXR0cmlidXRlcy5kaWxhdGlvbnMubGVuZ3RoICE9PSBzcGF0aWFsUmFuaykge1xuICAgIHRocm93IG5ldyBFcnJvcihgZGlsYXRpb25zIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rfURgKTtcbiAgfVxuXG4gIC8vIFdyb25nIHN0cmlkZXMgZGltZW5zaW9uXG4gIGlmIChhdHRyaWJ1dGVzLnN0cmlkZXMubGVuZ3RoICE9PSBzcGF0aWFsUmFuaykge1xuICAgIHRocm93IG5ldyBFcnJvcihgc3RyaWRlcyBzaG91bGQgYmUgJHtzcGF0aWFsUmFua31EYCk7XG4gIH1cblxuICAvLyBXcm9uZyBwYWRzIGRpbWVuc2lvblxuICBpZiAoYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAhPT0gc3BhdGlhbFJhbmsgKiAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBwYWRzIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rICogMn1EYCk7XG4gIH1cblxuICAvLyBpZiBrZXJuZWxTaGFwZSBpcyBzcGVjaWZpZWQsIGl0J3MgZGF0YSBsZW5ndGggbXVzdCBiZSAyIGxlc3MgdGhhbiBkaW1zIGxlbmd0aCBvZiB0aGUgd2VpZ2h0cyB0ZW5zb3JcbiAgLy8gKHRoZSBmaXJzdCAyIGRpbXMgYXJlIGJhdGNoX3NpemUgYW5kIGNoYW5uZWxzKVxuICBpZiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggIT09IDAgJiYgYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggIT09IGlucHV0c1sxXS5kaW1zLmxlbmd0aCAtIDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQga2VybmVsIHNoYXBlJyk7XG4gIH1cbn07XG5cbmNvbnN0IGdldEFkanVzdGVkQ29udkF0dHJpYnV0ZXMgPSA8VCBleHRlbmRzIENvbnZBdHRyaWJ1dGVzPihhdHRyaWJ1dGVzOiBULCBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IFQgPT4ge1xuICBjb25zdCBrZXJuZWxTaGFwZSA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGUuc2xpY2UoKTtcbiAgLy8gaWYga2VybmVsU2hhcGUgaXMgbm90IHdlbGwgc3BlY2lmaWVkIGluIHRoZSBhdHRyaWJ1dGVzLCBpbmZlciBpdCBmcm9tIHRoZSB3ZWlnaHQgdGVuc29yIGRpbXNcbiAgaWYgKGtlcm5lbFNoYXBlLmxlbmd0aCA8IGlucHV0c1sxXS5kaW1zLmxlbmd0aCAtIDIpIHtcbiAgICBrZXJuZWxTaGFwZS5wdXNoKC4uLkFycmF5KGlucHV0c1sxXS5kaW1zLmxlbmd0aCAtIDIgLSBrZXJuZWxTaGFwZS5sZW5ndGgpLmZpbGwoMCkpO1xuICB9XG4gIGZvciAobGV0IGkgPSAyOyBpIDwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoa2VybmVsU2hhcGVbaSAtIDJdID09PSAwKSB7XG4gICAgICBrZXJuZWxTaGFwZVtpIC0gMl0gPSBpbnB1dHNbMV0uZGltc1tpXTtcbiAgICB9XG4gIH1cbiAgY29uc3QgcGFkcyA9IGF0dHJpYnV0ZXMucGFkcy5zbGljZSgpO1xuICBQb29sQ29udlV0aWwuYWRqdXN0UGFkc0Jhc2VkT25BdXRvUGFkKFxuICAgIGlucHV0c1swXS5kaW1zLFxuICAgIGF0dHJpYnV0ZXMuc3RyaWRlcyxcbiAgICBhdHRyaWJ1dGVzLmRpbGF0aW9ucyxcbiAgICBrZXJuZWxTaGFwZSxcbiAgICBwYWRzLFxuICAgIGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQycsXG4gICAgYXR0cmlidXRlcy5hdXRvUGFkLFxuICApO1xuXG4gIC8vIGFsd2F5cyByZXR1cm4gYSBuZXcgb2JqZWN0IHNvIGRvZXMgbm90IG1vZGlmeSB0aGUgb3JpZ2luYWwgYXR0cmlidXRlc1xuICBjb25zdCBuZXdBdHRyaWJ1dGVzOiBUID0gT2JqZWN0LmFzc2lnbih7fSwgYXR0cmlidXRlcyk7XG4gIE9iamVjdC5hc3NpZ24obmV3QXR0cmlidXRlcywgeyBrZXJuZWxTaGFwZSwgcGFkcyB9KTtcbiAgcmV0dXJuIG5ld0F0dHJpYnV0ZXM7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VDb252QXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IENvbnZBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgYWN0aXZhdGlvbkF0dHJpYnV0ZXMgPSBwYXJzZUludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMoYXR0cmlidXRlcyk7XG4gIC8vIFRPRE8gOiBNYWtlIHRoaXMgZ2VuZXJpYyBlbm91Z2ggdG8gY29tcHV0ZSBkZWZhdWx0IGF0dHJpYnV0ZXMgZm9yIG11bHRpLWRpbWVuc2lvbmFsIGNvbnZcbiAgY29uc3QgZm9ybWF0ID0gYXR0cmlidXRlcy5mb3JtYXQgYXMgJ05IV0MnIHwgJ05DSFcnO1xuICBjb25zdCBhdXRvUGFkID0gWydOT1RTRVQnLCAnVkFMSUQnLCAnU0FNRV9VUFBFUicsICdTQU1FX0xPV0VSJ11bYXR0cmlidXRlcy5hdXRvX3BhZCBhcyBudW1iZXJdO1xuICBjb25zdCBkaWxhdGlvbnMgPSBhdHRyaWJ1dGVzLmRpbGF0aW9ucyBhcyBudW1iZXJbXTtcbiAgY29uc3QgZ3JvdXAgPSBhdHRyaWJ1dGVzLmdyb3VwIGFzIG51bWJlcjtcbiAgY29uc3Qga2VybmVsU2hhcGUgPSBhdHRyaWJ1dGVzLmtlcm5lbF9zaGFwZSBhcyBudW1iZXJbXTtcbiAgY29uc3QgcGFkcyA9IGF0dHJpYnV0ZXMucGFkcyBhcyBudW1iZXJbXTtcbiAgY29uc3Qgc3RyaWRlcyA9IGF0dHJpYnV0ZXMuc3RyaWRlcyBhcyBudW1iZXJbXTtcbiAgY29uc3Qgd0lzQ29uc3QgPSAoYXR0cmlidXRlcy53X2lzX2NvbnN0IGFzICgpID0+IGJvb2xlYW4pKCk7XG5cbiAgcmV0dXJuIHtcbiAgICBhdXRvUGFkLFxuICAgIGZvcm1hdCxcbiAgICBkaWxhdGlvbnMsXG4gICAgZ3JvdXAsXG4gICAga2VybmVsU2hhcGUsXG4gICAgcGFkcyxcbiAgICBzdHJpZGVzLFxuICAgIHdJc0NvbnN0LFxuICAgIC4uLmFjdGl2YXRpb25BdHRyaWJ1dGVzLFxuICAgIGNhY2hlS2V5OiBgJHthdHRyaWJ1dGVzLmZvcm1hdH07JHthY3RpdmF0aW9uQXR0cmlidXRlcy5hY3RpdmF0aW9ufTtgLFxuICB9O1xufTtcblxuY29uc3QgY29udjJkID0gKFxuICBjb250ZXh0OiBDb21wdXRlQ29udGV4dCxcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzLFxuICBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbj86IChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pID0+IG51bWJlcltdLFxuKTogdm9pZCA9PiB7XG4gIC8vIGNoZWNrIGF0dHJpYnV0ZXNcblxuICAvLyBjb25zdCBoYXNQcmVsdUFjdGl2YXRpb25XZWlnaHRzID0gZmFsc2U7IC8qIFRPRE86IGFkZCBzdXBwb3J0IGZvciBwcmVsdSBhY3RpdmF0aW9uIHdlaWdodHMgKi9cbiAgY29uc3QgaXNDaGFubmVsc0xhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGNhbGN1bGF0ZU91dHB1dFNoYXBlKFxuICAgIGlucHV0c1swXS5kaW1zLFxuICAgIGlucHV0c1sxXS5kaW1zLFxuICAgIGF0dHJpYnV0ZXMuZGlsYXRpb25zLFxuICAgIGF0dHJpYnV0ZXMucGFkcyxcbiAgICBhdHRyaWJ1dGVzLnN0cmlkZXMsXG4gICAgaXNDaGFubmVsc0xhc3QsXG4gICk7XG4gIGlmIChhdHRyaWJ1dGVzLmdyb3VwICE9PSAxKSB7XG4gICAgY29uc3QgY29udklucHV0cyA9IFtpbnB1dHNbMF1dO1xuICAgIGlmIChpc0NoYW5uZWxzTGFzdCkge1xuICAgICAgY29uc3QgdHJhbnNwb3NlZFdlaWdodCA9XG4gICAgICAgIChjb250ZXh0Lmtlcm5lbEN1c3RvbURhdGEud1QgYXMgVGVuc29yVmlldyB8IHVuZGVmaW5lZCkgPz9cbiAgICAgICAgY29udGV4dC5jb21wdXRlKGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvKGlucHV0c1sxXSwgd2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlKSwge1xuICAgICAgICAgIGlucHV0czogWzFdLFxuICAgICAgICAgIG91dHB1dHM6IFthdHRyaWJ1dGVzLndJc0NvbnN0ID8gLTIgOiAtMV0sXG4gICAgICAgIH0pWzBdO1xuICAgICAgaWYgKGF0dHJpYnV0ZXMud0lzQ29uc3QgJiYgIWNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCkge1xuICAgICAgICBjb250ZXh0Lmtlcm5lbEN1c3RvbURhdGEud1QgPSB0cmFuc3Bvc2VkV2VpZ2h0O1xuICAgICAgfVxuICAgICAgY29udklucHV0cy5wdXNoKHRyYW5zcG9zZWRXZWlnaHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb252SW5wdXRzLnB1c2goaW5wdXRzWzFdKTtcbiAgICB9XG4gICAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMpIHtcbiAgICAgIGNvbnZJbnB1dHMucHVzaChpbnB1dHNbMl0pO1xuICAgIH1cbiAgICAvLyBOVklESUEgR1BVIHdpdGggYW1wZXJlIGFyY2hpdGVjdHVyZSBmYWlscyB3aXRoIGJlbG93IDIgY2FzZXMsIGJ1dCB3ZSBjb3VsZG4ndCByZXBybyB0aGVtIHdpdGggYW55IG90aGVyXG4gICAgLy8gR1BVcy4gU28ganVzdCBkaXNhYmxlIHZlY3Rvcml6ZSBvbiBOVklESUEgYW1wZXJlIHRvIGVuc3VyZSBhbHdheXMgY29ycmVjdCBvdXRwdXRzLlxuICAgIC8vIFt3ZWJncHVdQ29udiAtIGNvbnYgLSB2ZWN0b3JpemUgZ3JvdXAgLSBCXG4gICAgLy8gW3dlYmdwdV1Db252IC0gY29udiAtIHZlY3Rvcml6ZSBncm91cCAtIERcbiAgICBjb25zdCBlbmFibGVHcm91cGVkQ29udlZlY3Rvcml6ZSA9ICFjb250ZXh0LmFkYXB0ZXJJbmZvLmlzQXJjaGl0ZWN0dXJlKCdhbXBlcmUnKTtcbiAgICBpZiAoXG4gICAgICBlbmFibGVHcm91cGVkQ29udlZlY3Rvcml6ZSAmJlxuICAgICAgaXNDaGFubmVsc0xhc3QgJiZcbiAgICAgIGlucHV0c1sxXS5kaW1zWzBdID09PSBhdHRyaWJ1dGVzLmdyb3VwICYmXG4gICAgICBpbnB1dHNbMV0uZGltc1sxXSA9PT0gMSAmJlxuICAgICAgYXR0cmlidXRlcy5kaWxhdGlvbnNbMF0gPT09IDEgJiZcbiAgICAgIGF0dHJpYnV0ZXMuZGlsYXRpb25zWzFdID09PSAxXG4gICAgKSB7XG4gICAgICBjb250ZXh0LmNvbXB1dGUoXG4gICAgICAgIGNyZWF0ZUdyb3VwZWRDb252VmVjdG9yaXplUHJvZ3JhbUluZm8oY29udklucHV0cywgYXR0cmlidXRlcywgb3V0cHV0U2hhcGUsIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uKSxcbiAgICAgICAgeyBpbnB1dHM6IGNvbnZJbnB1dHMgfSxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVHcm91cGVkQ29udlByb2dyYW1JbmZvKGNvbnZJbnB1dHMsIGF0dHJpYnV0ZXMsIG91dHB1dFNoYXBlLCBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbiksIHtcbiAgICAgICAgaW5wdXRzOiBjb252SW5wdXRzLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGhhc0JpYXMgPSBpbnB1dHMubGVuZ3RoID09PSAzO1xuICBjb25zdCBpbnB1dEhlaWdodCA9IGlucHV0c1swXS5kaW1zW2lzQ2hhbm5lbHNMYXN0ID8gMSA6IDJdO1xuICBjb25zdCBpbnB1dFdpZHRoID0gaW5wdXRzWzBdLmRpbXNbaXNDaGFubmVsc0xhc3QgPyAyIDogM107XG4gIGNvbnN0IGlucHV0Q2hhbm5lbHMgPSBpbnB1dHNbMF0uZGltc1tpc0NoYW5uZWxzTGFzdCA/IDMgOiAxXTtcbiAgY29uc3Qgd2VpZ2h0SGVpZ2h0ID0gaW5wdXRzWzFdLmRpbXNbMl07XG4gIGNvbnN0IHdlaWdodFdpZHRoID0gaW5wdXRzWzFdLmRpbXNbM107XG5cbiAgY29uc3Qgb3V0SGVpZ2h0ID0gb3V0cHV0U2hhcGVbaXNDaGFubmVsc0xhc3QgPyAxIDogMl07XG4gIGNvbnN0IG91dFdpZHRoID0gb3V0cHV0U2hhcGVbaXNDaGFubmVsc0xhc3QgPyAyIDogM107XG4gIGNvbnN0IG91dENoYW5uZWxzID0gb3V0cHV0U2hhcGVbaXNDaGFubmVsc0xhc3QgPyAzIDogMV07XG5cbiAgY29uc3Qgc2FtZVNpemUgPVxuICAgIGlzQ2hhbm5lbHNMYXN0ICYmXG4gICAgd2VpZ2h0SGVpZ2h0ID09PSBpbnB1dEhlaWdodCAmJlxuICAgIHdlaWdodFdpZHRoID09PSBpbnB1dFdpZHRoICYmXG4gICAgYXR0cmlidXRlcy5wYWRzWzBdID09PSAwICYmXG4gICAgYXR0cmlidXRlcy5wYWRzWzFdID09PSAwO1xuICBpZiAoXG4gICAgc2FtZVNpemUgfHxcbiAgICAod2VpZ2h0SGVpZ2h0ID09PSAxICYmXG4gICAgICB3ZWlnaHRXaWR0aCA9PT0gMSAmJlxuICAgICAgYXR0cmlidXRlcy5kaWxhdGlvbnNbMF0gPT09IDEgJiZcbiAgICAgIGF0dHJpYnV0ZXMuZGlsYXRpb25zWzFdID09PSAxICYmXG4gICAgICBhdHRyaWJ1dGVzLnN0cmlkZXNbMF0gPT09IDEgJiZcbiAgICAgIGF0dHJpYnV0ZXMuc3RyaWRlc1sxXSA9PT0gMSAmJlxuICAgICAgYXR0cmlidXRlcy5wYWRzWzBdID09PSAwICYmXG4gICAgICBhdHRyaWJ1dGVzLnBhZHNbMV0gPT09IDApXG4gICkge1xuICAgIC8vIGNvbnYyZEJ5TWF0TXVsXG4gICAgY29uc3QgYmF0Y2ggPSBvdXRwdXRTaGFwZVswXTtcbiAgICBsZXQgeFJlc2hhcGVkLCB3UmVzaGFwZWQsIG1hdG11bE91dHB1dFNoYXBlO1xuICAgIGNvbnN0IG1hdG11bElucHV0cyA9IFtdO1xuICAgIGlmIChpc0NoYW5uZWxzTGFzdCkge1xuICAgICAgY29uc3QgdHJhbnNwb3NlZFdlaWdodCA9XG4gICAgICAgIChjb250ZXh0Lmtlcm5lbEN1c3RvbURhdGEud1QgYXMgVGVuc29yVmlldyB8IHVuZGVmaW5lZCkgPz9cbiAgICAgICAgY29udGV4dC5jb21wdXRlKGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvKGlucHV0c1sxXSwgd2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlKSwge1xuICAgICAgICAgIGlucHV0czogWzFdLFxuICAgICAgICAgIG91dHB1dHM6IFthdHRyaWJ1dGVzLndJc0NvbnN0ID8gLTIgOiAtMV0sXG4gICAgICAgIH0pWzBdO1xuICAgICAgaWYgKGF0dHJpYnV0ZXMud0lzQ29uc3QgJiYgIWNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCkge1xuICAgICAgICBjb250ZXh0Lmtlcm5lbEN1c3RvbURhdGEud1QgPSB0cmFuc3Bvc2VkV2VpZ2h0O1xuICAgICAgfVxuICAgICAgaWYgKHNhbWVTaXplKSB7XG4gICAgICAgIGNvbnN0IHNoYXJlZERpbSA9IGlucHV0SGVpZ2h0ICogaW5wdXRXaWR0aCAqIGlucHV0Q2hhbm5lbHM7XG4gICAgICAgIHhSZXNoYXBlZCA9IGlucHV0c1swXS5yZXNoYXBlKFsxLCBiYXRjaCwgc2hhcmVkRGltXSk7XG4gICAgICAgIHdSZXNoYXBlZCA9IHRyYW5zcG9zZWRXZWlnaHQucmVzaGFwZShbMSwgc2hhcmVkRGltLCBvdXRDaGFubmVsc10pO1xuICAgICAgICBtYXRtdWxPdXRwdXRTaGFwZSA9IFsxLCBiYXRjaCwgb3V0Q2hhbm5lbHNdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgeFJlc2hhcGVkID0gaW5wdXRzWzBdLnJlc2hhcGUoW2JhdGNoLCBpbnB1dEhlaWdodCAqIGlucHV0V2lkdGgsIGlucHV0Q2hhbm5lbHNdKTtcbiAgICAgICAgd1Jlc2hhcGVkID0gdHJhbnNwb3NlZFdlaWdodC5yZXNoYXBlKFsxLCBpbnB1dENoYW5uZWxzLCBvdXRDaGFubmVsc10pO1xuICAgICAgICBtYXRtdWxPdXRwdXRTaGFwZSA9IFtiYXRjaCwgb3V0SGVpZ2h0ICogb3V0V2lkdGgsIG91dENoYW5uZWxzXTtcbiAgICAgIH1cbiAgICAgIG1hdG11bElucHV0cy5wdXNoKHhSZXNoYXBlZCk7XG4gICAgICBtYXRtdWxJbnB1dHMucHVzaCh3UmVzaGFwZWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB4UmVzaGFwZWQgPSBpbnB1dHNbMF0ucmVzaGFwZShbYmF0Y2gsIGlucHV0Q2hhbm5lbHMsIGlucHV0SGVpZ2h0ICogaW5wdXRXaWR0aF0pO1xuICAgICAgd1Jlc2hhcGVkID0gaW5wdXRzWzFdLnJlc2hhcGUoWzEsIG91dENoYW5uZWxzLCBpbnB1dENoYW5uZWxzXSk7XG4gICAgICBtYXRtdWxPdXRwdXRTaGFwZSA9IFtiYXRjaCwgb3V0Q2hhbm5lbHMsIG91dEhlaWdodCAqIG91dFdpZHRoXTtcbiAgICAgIG1hdG11bElucHV0cy5wdXNoKHdSZXNoYXBlZCk7XG4gICAgICBtYXRtdWxJbnB1dHMucHVzaCh4UmVzaGFwZWQpO1xuICAgIH1cbiAgICBpZiAoaGFzQmlhcykge1xuICAgICAgbWF0bXVsSW5wdXRzLnB1c2goaW5wdXRzWzJdKTtcbiAgICB9XG4gICAgY29uc3QgTiA9IG1hdG11bE91dHB1dFNoYXBlWzJdO1xuICAgIGNvbnN0IEsgPSBtYXRtdWxJbnB1dHNbMF0uZGltc1ttYXRtdWxJbnB1dHNbMF0uZGltcy5sZW5ndGggLSAxXTtcbiAgICAvLyBUdW5lIHRoZSB0aHJlc2hvbGQuXG4gICAgaWYgKE4gPCA4ICYmIEsgPCA4KSB7XG4gICAgICBjb250ZXh0LmNvbXB1dGUoXG4gICAgICAgIGNyZWF0ZU5haXZlTWF0bXVsUHJvZ3JhbUluZm8oXG4gICAgICAgICAgbWF0bXVsSW5wdXRzLFxuICAgICAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICAgICAgb3V0cHV0U2hhcGUsXG4gICAgICAgICAgbWF0bXVsT3V0cHV0U2hhcGUsXG4gICAgICAgICAgaXNDaGFubmVsc0xhc3QsXG4gICAgICAgICAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24sXG4gICAgICAgICksXG4gICAgICAgIHsgaW5wdXRzOiBtYXRtdWxJbnB1dHMgfSxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnRleHQuY29tcHV0ZShcbiAgICAgICAgY3JlYXRlTWF0bXVsUHJvZ3JhbUluZm8oXG4gICAgICAgICAgbWF0bXVsSW5wdXRzLFxuICAgICAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICAgICAgb3V0cHV0U2hhcGUsXG4gICAgICAgICAgbWF0bXVsT3V0cHV0U2hhcGUsXG4gICAgICAgICAgaXNDaGFubmVsc0xhc3QsXG4gICAgICAgICAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24sXG4gICAgICAgICksXG4gICAgICAgIHsgaW5wdXRzOiBtYXRtdWxJbnB1dHMgfSxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFRPRE86IGltcGxlbWVudCBjb252MmRXaXRoSW0yQ29sKClcblxuICBjb25zdCBzZXF1ZW50aWFsQWNjZXNzQnlUaHJlYWRzID0gLyogYmFja2VuZC5hZGFwdGVySW5mby5pc0ludGVsKCkgKi8gdHJ1ZTtcblxuICAvLyBTVEVQLjE6IHRyYW5zcG9zZSB3ZWlnaHRcbiAgY29uc3QgdHJhbnNwb3NlZFdlaWdodCA9XG4gICAgKGNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCBhcyBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkKSA/P1xuICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhpbnB1dHNbMV0sIHdlaWdodFRyYW5zcG9zZUF0dHJpYnV0ZSksIHtcbiAgICAgIGlucHV0czogWzFdLFxuICAgICAgb3V0cHV0czogW2F0dHJpYnV0ZXMud0lzQ29uc3QgPyAtMiA6IC0xXSxcbiAgICB9KVswXTtcbiAgaWYgKGF0dHJpYnV0ZXMud0lzQ29uc3QgJiYgIWNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCkge1xuICAgIGNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCA9IHRyYW5zcG9zZWRXZWlnaHQ7XG4gIH1cblxuICAvLyBTVEVQLjI6IHByZXBhcmUgcmVzaGFwZWQgaW5wdXRzXG4gIGNvbnN0IGNvbnZJbnB1dHMgPSBbaW5wdXRzWzBdLCB0cmFuc3Bvc2VkV2VpZ2h0XTtcbiAgaWYgKGhhc0JpYXMpIHtcbiAgICBjb252SW5wdXRzLnB1c2goaW5wdXRzWzJdKTtcbiAgfVxuXG4gIC8vIFNURVAuMzogY29tcHV0ZSBtYXRtdWxcbiAgY29uc3QgZGltQU91dGVyID0gaXNDaGFubmVsc0xhc3QgPyBvdXRIZWlnaHQgKiBvdXRXaWR0aCA6IG91dENoYW5uZWxzO1xuICBjb25zdCBkaW1CT3V0ZXIgPSBpc0NoYW5uZWxzTGFzdCA/IG91dENoYW5uZWxzIDogb3V0SGVpZ2h0ICogb3V0V2lkdGg7XG4gIGNvbnN0IGRpbUlubmVyID0gd2VpZ2h0SGVpZ2h0ICogd2VpZ2h0V2lkdGggKiBpbnB1dENoYW5uZWxzO1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAgY3JlYXRlQ29udjJETWF0TXVsUHJvZ3JhbUluZm8oXG4gICAgICBjb252SW5wdXRzLFxuICAgICAgYXR0cmlidXRlcyxcbiAgICAgIG91dHB1dFNoYXBlLFxuICAgICAgZGltQU91dGVyLFxuICAgICAgZGltQk91dGVyLFxuICAgICAgZGltSW5uZXIsXG4gICAgICBoYXNCaWFzLFxuICAgICAgc2VxdWVudGlhbEFjY2Vzc0J5VGhyZWFkcyxcbiAgICAgIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uLFxuICAgICksXG4gICAgeyBpbnB1dHM6IGNvbnZJbnB1dHMgfSxcbiAgKTtcbn07XG5cbmNvbnN0IGNvbnYxZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgLy8gZXh0ZW5kIHRoZSBpbnB1dCB0byAyRCBieSBhZGRpbmcgSCBkaW1lbnNpb25cbiAgY29uc3QgaXNDaGFubmVsTGFzdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQyc7XG4gIGNvbnN0IGlucHV0cyA9IFtcbiAgICBjb250ZXh0LmlucHV0c1swXS5yZXNoYXBlKFxuICAgICAgaXNDaGFubmVsTGFzdFxuICAgICAgICA/IC8vIFtOLCBXLCBDXSAtPiBbTiwgSD0xLCBXLCBDXVxuICAgICAgICAgIFtjb250ZXh0LmlucHV0c1swXS5kaW1zWzBdLCAxLCBjb250ZXh0LmlucHV0c1swXS5kaW1zWzFdLCBjb250ZXh0LmlucHV0c1swXS5kaW1zWzJdXVxuICAgICAgICA6IC8vIFtOLCBDLCBXXSAtPiBbTiwgQywgSD0xLCBXXVxuICAgICAgICAgIFtjb250ZXh0LmlucHV0c1swXS5kaW1zWzBdLCBjb250ZXh0LmlucHV0c1swXS5kaW1zWzFdLCAxLCBjb250ZXh0LmlucHV0c1swXS5kaW1zWzJdXSxcbiAgICApLFxuICAgIC8vW0ZJTFRFUl9PVVRfQ0hBTk5FTCwgRklMVEVSX0lOX0NIQU5ORUwsIGtXXSAtPiBbRklMVEVSX09VVF9DSEFOTkVMLCBGSUxURVJfSU5fQ0hBTk5FTCwga0g9MSwga1ddXG4gICAgY29udGV4dC5pbnB1dHNbMV0ucmVzaGFwZShbY29udGV4dC5pbnB1dHNbMV0uZGltc1swXSwgY29udGV4dC5pbnB1dHNbMV0uZGltc1sxXSwgMSwgY29udGV4dC5pbnB1dHNbMV0uZGltc1syXV0pLFxuICBdO1xuICBpZiAoY29udGV4dC5pbnB1dHMubGVuZ3RoID09PSAzKSB7XG4gICAgaW5wdXRzLnB1c2goY29udGV4dC5pbnB1dHNbMl0pO1xuICB9XG4gIGNvbnN0IHBhZHMgPSBbMCwgYXR0cmlidXRlcy5wYWRzWzBdLCAwLCBhdHRyaWJ1dGVzLnBhZHNbMV1dO1xuICBjb25zdCBzdHJpZGVzID0gWzFdLmNvbmNhdChhdHRyaWJ1dGVzLnN0cmlkZXMpO1xuICBjb25zdCBkaWxhdGlvbnMgPSBbMV0uY29uY2F0KGF0dHJpYnV0ZXMuZGlsYXRpb25zKTtcbiAgY29uc3Qga2VybmVsU2hhcGUgPSBbMV0uY29uY2F0KGF0dHJpYnV0ZXMua2VybmVsU2hhcGUpO1xuICBjb25zdCBhZGp1c3RlZEF0dHJpYnV0ZXMgPSBnZXRBZGp1c3RlZENvbnZBdHRyaWJ1dGVzKFxuICAgIHsgLi4uYXR0cmlidXRlcywgcGFkcywgc3RyaWRlcywgZGlsYXRpb25zLCBrZXJuZWxTaGFwZSB9LFxuICAgIGlucHV0cyxcbiAgKTtcbiAgY29udjJkKGNvbnRleHQsIGlucHV0cywgYWRqdXN0ZWRBdHRyaWJ1dGVzLCAob3V0cHV0U2hhcGUpID0+XG4gICAgaXNDaGFubmVsTGFzdCA/IFtvdXRwdXRTaGFwZVswXSwgb3V0cHV0U2hhcGVbMl0sIG91dHB1dFNoYXBlWzNdXSA6IFtvdXRwdXRTaGFwZVswXSwgb3V0cHV0U2hhcGVbMV0sIG91dHB1dFNoYXBlWzNdXSxcbiAgKTtcbn07XG5cbmNvbnN0IGNvbnYzZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IGZvcm1hdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQycgPyAnY2hhbm5lbHNMYXN0JyA6ICdjaGFubmVsc0ZpcnN0JztcbiAgY29uc3QgYWRqdXN0ZWRBdHRyaWJ1dGVzID0gZ2V0QWRqdXN0ZWRDb252QXR0cmlidXRlcyhhdHRyaWJ1dGVzLCBpbnB1dHMpO1xuICBjb25zdCBwYWRzID0gYXR0cmlidXRlcy5hdXRvUGFkID09PSAnTk9UU0VUJyA/IGF0dHJpYnV0ZXMucGFkcyA6IGF0dHJpYnV0ZXMuYXV0b1BhZDtcbiAgY29uc3QgY29udkluZm8gPSBjb21wdXRlQ29udjNESW5mbyhcbiAgICBpbnB1dHNbMF0uZGltcyBhcyBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICAgIGlucHV0c1sxXS5kaW1zIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICAgYXR0cmlidXRlcy5zdHJpZGVzIGFzIG51bWJlciB8IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbiAgICBhdHRyaWJ1dGVzLmRpbGF0aW9ucyBhcyBudW1iZXIgfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICAgcGFkcyBhcyBzdHJpbmcgfCBudW1iZXJbXSxcbiAgICBmYWxzZSxcbiAgICBmb3JtYXQsXG4gICk7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICBjcmVhdGVDb252M0ROYWl2ZVByb2dyYW1JbmZvKFxuICAgICAgaW5wdXRzLFxuICAgICAgYWRqdXN0ZWRBdHRyaWJ1dGVzLFxuICAgICAgY29udkluZm8ub3V0U2hhcGUsXG4gICAgICBbY29udkluZm8uZmlsdGVyRGVwdGgsIGNvbnZJbmZvLmZpbHRlckhlaWdodCwgY29udkluZm8uZmlsdGVyV2lkdGhdLFxuICAgICAgW2NvbnZJbmZvLnBhZEluZm8uZnJvbnQsIGNvbnZJbmZvLnBhZEluZm8udG9wLCBjb252SW5mby5wYWRJbmZvLmxlZnRdLFxuICAgICAgZm9ybWF0LFxuICAgICksXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgY29udiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICBpZiAoY29udGV4dC5pbnB1dHNbMF0uZGltcy5sZW5ndGggPT09IDMpIHtcbiAgICBjb252MWQoY29udGV4dCwgYXR0cmlidXRlcyk7XG4gIH0gZWxzZSBpZiAoY29udGV4dC5pbnB1dHNbMF0uZGltcy5sZW5ndGggPT09IDUpIHtcbiAgICBjb252M2QoY29udGV4dCwgY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IGFkanVzdGVkQXR0cmlidXRlcyA9IGdldEFkanVzdGVkQ29udkF0dHJpYnV0ZXMoYXR0cmlidXRlcywgY29udGV4dC5pbnB1dHMpO1xuICAgIGNvbnYyZChjb250ZXh0LCBjb250ZXh0LmlucHV0cywgYWRqdXN0ZWRBdHRyaWJ1dGVzKTtcbiAgfVxufTtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbi8vIHNhbXBsZWQgZnJvbSBbQHRlbnNvcmZsb3cvdGZqc10gdGZqcy1iYWNrZW5kLXdlYmdwdS9zcmMvY29udl9iYWNrcHJvcF93ZWJncHUudHNcblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBMT0dfREVCVUcgfSBmcm9tICcuLi8uLi8uLi9sb2cnO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgUHJvZ3JhbUluZm8sIFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uLy4uL3R5cGVzJztcbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxuICBnZXRNYXhDb21wb25lbnRzLFxufSBmcm9tICcuLi9jb21tb24nO1xuaW1wb3J0IHsgQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMgfSBmcm9tICcuLi9jb252LXRyYW5zcG9zZSc7XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVDb252VHJhbnNwb3NlMkRQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzLFxuICBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbj86IChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pID0+IG51bWJlcltdLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBoYXNCaWFzID0gaW5wdXRzLmxlbmd0aCA+IDI7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gYXR0cmlidXRlcy5vdXRwdXRTaGFwZTtcbiAgY29uc3QgaXNDaGFubmVsc0xhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuICBjb25zdCBncm91cCA9IGF0dHJpYnV0ZXMuZ3JvdXA7XG4gIGNvbnN0IHdTaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuICBjb25zdCBpbnB1dENoYW5uZWxzUGVyR3JvdXAgPSB3U2hhcGVbMl0gLyBncm91cDtcbiAgY29uc3Qgb3V0cHV0Q2hhbm5lbHNQZXJHcm91cCA9IHdTaGFwZVszXTtcbiAgY29uc3QgYUNvbXBvbmVudHMgPSBpc0NoYW5uZWxzTGFzdCA/IGdldE1heENvbXBvbmVudHMoaW5wdXRDaGFubmVsc1Blckdyb3VwKSA6IDE7XG4gIGNvbnN0IHBhY2tJbnB1dEFzNCA9IGlzQ2hhbm5lbHNMYXN0ICYmIG91dHB1dENoYW5uZWxzUGVyR3JvdXAgPT09IDEgJiYgaW5wdXRDaGFubmVsc1Blckdyb3VwID49IDQ7XG4gIGNvbnN0IGlucHV0Q2hhbm5lbHNQZXJHcm91cEludCA9IHBhY2tJbnB1dEFzNFxuICAgID8gTWF0aC5mbG9vcihpbnB1dENoYW5uZWxzUGVyR3JvdXAgLyA0KSAqIDRcbiAgICA6IE1hdGguZmxvb3IoaW5wdXRDaGFubmVsc1Blckdyb3VwIC8gYUNvbXBvbmVudHMpICogYUNvbXBvbmVudHM7XG4gIGNvbnN0IGlucHV0Q2hhbm5lbHNSZW1haW5kZXIgPSBpbnB1dENoYW5uZWxzUGVyR3JvdXAgLSBpbnB1dENoYW5uZWxzUGVyR3JvdXBJbnQ7XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBpc0NoYW5uZWxzTGFzdCA/IGdldE1heENvbXBvbmVudHMob3V0cHV0Q2hhbm5lbHNQZXJHcm91cCkgOiAxO1xuICBjb25zdCBiQ29tcG9uZW50cyA9IGlzQ2hhbm5lbHNMYXN0ID8gKG91dHB1dENoYW5uZWxzUGVyR3JvdXAgPT09IDEgPyBhQ29tcG9uZW50cyA6IGNvbXBvbmVudHMpIDogMTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIGNvbXBvbmVudHM7XG4gIGNvbnN0IGRpc3BhdGNoID0gW01hdGguY2VpbChvdXRwdXRTaXplIC8gNjQpLCAxLCAxXTtcbiAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtjb252MmRfYmFja3Byb3Bfd2ViZ3B1XSBkaXNwYXRjaCA9ICR7ZGlzcGF0Y2h9YCk7XG5cbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3JhbmsnLCAncmFuayddO1xuICBjb25zdCBzdHJpZGVzID0gW2F0dHJpYnV0ZXMuc3RyaWRlc1swXSwgYXR0cmlidXRlcy5zdHJpZGVzWzFdXTtcbiAgY29uc3QgZmlsdGVyRGltcyA9IFthdHRyaWJ1dGVzLmtlcm5lbFNoYXBlW2lzQ2hhbm5lbHNMYXN0ID8gMSA6IDJdLCBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlW2lzQ2hhbm5lbHNMYXN0ID8gMiA6IDNdXTtcbiAgY29uc3QgZGlsYXRpb25zID0gW2F0dHJpYnV0ZXMuZGlsYXRpb25zWzBdLCBhdHRyaWJ1dGVzLmRpbGF0aW9uc1sxXV07XG4gIGNvbnN0IGVmZmVjdGl2ZUZpbHRlckRpbXMgPSBbXG4gICAgZmlsdGVyRGltc1swXSArXG4gICAgICAoYXR0cmlidXRlcy5kaWxhdGlvbnNbMF0gPD0gMVxuICAgICAgICA/IDBcbiAgICAgICAgOiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZVtpc0NoYW5uZWxzTGFzdCA/IDEgOiAyXSAtIDEpICogKGF0dHJpYnV0ZXMuZGlsYXRpb25zWzBdIC0gMSkpLFxuICAgIGZpbHRlckRpbXNbMV0gK1xuICAgICAgKGF0dHJpYnV0ZXMuZGlsYXRpb25zWzFdIDw9IDFcbiAgICAgICAgPyAwXG4gICAgICAgIDogKGF0dHJpYnV0ZXMua2VybmVsU2hhcGVbaXNDaGFubmVsc0xhc3QgPyAyIDogM10gLSAxKSAqIChhdHRyaWJ1dGVzLmRpbGF0aW9uc1sxXSAtIDEpKSxcbiAgXTtcbiAgY29uc3QgcGFkcyA9IFtcbiAgICBlZmZlY3RpdmVGaWx0ZXJEaW1zWzBdIC0gMSAtIE1hdGguZmxvb3IoKGF0dHJpYnV0ZXMucGFkc1swXSArIGF0dHJpYnV0ZXMucGFkc1syXSkgLyAyKSxcbiAgICBlZmZlY3RpdmVGaWx0ZXJEaW1zWzFdIC0gMSAtIE1hdGguZmxvb3IoKGF0dHJpYnV0ZXMucGFkc1sxXSArIGF0dHJpYnV0ZXMucGFkc1szXSkgLyAyKSxcbiAgXTtcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogc3RyaWRlcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBmaWx0ZXJEaW1zIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGRpbGF0aW9ucyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBlZmZlY3RpdmVGaWx0ZXJEaW1zIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogcGFkcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBpbnB1dENoYW5uZWxzUGVyR3JvdXBJbnQgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogaW5wdXRDaGFubmVsc1Blckdyb3VwIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dENoYW5uZWxzUGVyR3JvdXAgfSxcbiAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMF0uZGltcywgaW5wdXRzWzFdLmRpbXMpLFxuICBdO1xuICBpZiAoaGFzQmlhcykge1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1syXS5kaW1zKSk7XG4gICAgaW5wdXREZXBlbmRlbmNpZXMucHVzaCgncmFuaycpO1xuICB9XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dHB1dFNoYXBlKSk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgdW5pZm9ybXM6IFVuaWZvcm1zQXJyYXlUeXBlID0gW1xuICAgICAgeyBuYW1lOiAnb3V0cHV0X3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnc3RyaWRlcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IHN0cmlkZXMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdmaWx0ZXJfZGltcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGZpbHRlckRpbXMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdkaWxhdGlvbnMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBmaWx0ZXJEaW1zLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAnZWZmZWN0aXZlX2ZpbHRlcl9kaW1zJywgdHlwZTogJ3UzMicsIGxlbmd0aDogZWZmZWN0aXZlRmlsdGVyRGltcy5sZW5ndGggfSxcbiAgICAgIHsgbmFtZTogJ3BhZHMnLCB0eXBlOiAnaTMyJywgbGVuZ3RoOiBwYWRzLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAnaW5wdXRfY2hhbm5lbHNfcGVyX2dyb3VwX2ludCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdpbnB1dF9jaGFubmVsc19wZXJfZ3JvdXAnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnb3V0cHV0X2NoYW5uZWxzX3Blcl9ncm91cCcsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcbiAgICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShpbnB1dHNbMF0uZGF0YVR5cGUpO1xuICAgIGNvbnN0IHJvd0RpbSA9IGlzQ2hhbm5lbHNMYXN0ID8gMSA6IDI7XG4gICAgY29uc3QgY29sRGltID0gaXNDaGFubmVsc0xhc3QgPyAyIDogMztcbiAgICBjb25zdCBjaGFubmVsRGltID0gaXNDaGFubmVsc0xhc3QgPyAzIDogMTtcblxuICAgIGNvbnN0IHcgPSBpbnB1dFZhcmlhYmxlKCdXJywgaW5wdXRzWzFdLmRhdGFUeXBlLCBpbnB1dHNbMV0uZGltcy5sZW5ndGgsIGJDb21wb25lbnRzKTtcbiAgICBjb25zdCBkeSA9IGlucHV0VmFyaWFibGUoJ0R5JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcy5sZW5ndGgsIGFDb21wb25lbnRzKTtcbiAgICBjb25zdCBpbnB1dFZhcmlhYmxlcyA9IFtkeSwgd107XG4gICAgaWYgKGhhc0JpYXMpIHtcbiAgICAgIGlucHV0VmFyaWFibGVzLnB1c2goaW5wdXRWYXJpYWJsZSgnYmlhcycsIGlucHV0c1syXS5kYXRhVHlwZSwgW291dHB1dFNoYXBlW2NoYW5uZWxEaW1dXS5sZW5ndGgsIGNvbXBvbmVudHMpKTtcbiAgICB9XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ3Jlc3VsdCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcblxuICAgIGNvbnN0IGNhbGN1bGF0ZVJlc3VsdCA9ICgpOiBzdHJpbmcgPT4ge1xuICAgICAgbGV0IGNhbGNTdHIgPSAnJztcbiAgICAgIGlmIChwYWNrSW5wdXRBczQpIHtcbiAgICAgICAgaWYgKGFDb21wb25lbnRzID09PSA0KSB7XG4gICAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgIGxldCB4VmFsdWUgPSAke2R5LmdldEJ5T2Zmc2V0KCd4X29mZnNldCcpfTtcbiAgICAgICAgbGV0IHdWYWx1ZSA9ICR7dy5nZXRCeU9mZnNldCgnd19vZmZzZXQnKX07XG4gICAgICAgIGRvdFByb2QgPSBkb3RQcm9kICsgZG90KHhWYWx1ZSwgd1ZhbHVlKTtcbiAgICAgICAgeF9vZmZzZXQgKz0gMXU7XG4gICAgICAgIHdfb2Zmc2V0ICs9IDF1O2A7XG4gICAgICAgIH0gZWxzZSBpZiAoYUNvbXBvbmVudHMgPT09IDIpIHtcbiAgICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICBkb3RQcm9kID0gZG90UHJvZCArIGRvdCh2ZWM0PCR7ZGF0YVR5cGV9Pigke2R5LmdldEJ5T2Zmc2V0KCd4X29mZnNldCcpfSwgJHtkeS5nZXRCeU9mZnNldCgneF9vZmZzZXQgKyAxdScpfSksIHZlYzQ8JHtkYXRhVHlwZX0+KCR7dy5nZXRCeU9mZnNldCgnd19vZmZzZXQnKX0sICR7dy5nZXRCeU9mZnNldCgnd19vZmZzZXQgKyAxdScpfSkpO1xuICAgICAgICAgIHhfb2Zmc2V0ICs9IDJ1O1xuICAgICAgICAgIHdfb2Zmc2V0ICs9IDJ1O2A7XG4gICAgICAgIH0gZWxzZSBpZiAoYUNvbXBvbmVudHMgPT09IDEpIHtcbiAgICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICBkb3RQcm9kID0gZG90UHJvZCArIGRvdCh2ZWM0PCR7ZGF0YVR5cGV9Pigke2R5LmdldEJ5T2Zmc2V0KCd4X29mZnNldCcpfSwgJHtkeS5nZXRCeU9mZnNldCgneF9vZmZzZXQgKyAxdScpfSwgJHtkeS5nZXRCeU9mZnNldCgneF9vZmZzZXQgKyAydScpfSwgJHtkeS5nZXRCeU9mZnNldCgneF9vZmZzZXQgKyAzdScpfSksIHZlYzQ8JHtkYXRhVHlwZX0+KCR7dy5nZXRCeU9mZnNldCgnd19vZmZzZXQnKX0sICR7dy5nZXRCeU9mZnNldCgnd19vZmZzZXQgKyAxdScpfSwgJHt3LmdldEJ5T2Zmc2V0KCd3X29mZnNldCArIDJ1Jyl9LCAke3cuZ2V0QnlPZmZzZXQoJ3dfb2Zmc2V0ICsgM3UnKX0pKTtcbiAgICAgICAgICB4X29mZnNldCArPSA0dTtcbiAgICAgICAgICB3X29mZnNldCArPSA0dTtgO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICAgICAgICAgIGxldCB4VmFsdWUgPSAke1xuICAgICAgICAgICAgICAgICAgICBpc0NoYW5uZWxzTGFzdFxuICAgICAgICAgICAgICAgICAgICAgID8gZHkuZ2V0QnlPZmZzZXQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGAke2R5LmluZGljZXNUb09mZnNldChgJHtkeS50eXBlLmluZGljZXN9KGJhdGNoLCBpZHlSLCBpZHlDLCBpbnB1dENoYW5uZWwpYCl9IC8gJHthQ29tcG9uZW50c31gLFxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgIDogZHkuZ2V0KCdiYXRjaCcsICdpbnB1dENoYW5uZWwnLCAnaWR5UicsICdpZHlDJylcbiAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgIGA7XG4gICAgICAgIGlmIChhQ29tcG9uZW50cyA9PT0gMSkge1xuICAgICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgIGxldCB3X29mZnNldCA9ICR7dy5pbmRpY2VzVG9PZmZzZXQoYCR7dy50eXBlLmluZGljZXN9KHUzMih3UlBlcm0pLCB1MzIod0NQZXJtKSwgaW5wdXRDaGFubmVsLCB3T3V0Q2hhbm5lbClgKX07XG4gICAgICAgICAgbGV0IHdWYWx1ZSA9ICR7dy5nZXRCeU9mZnNldChgd19vZmZzZXQgLyAke2JDb21wb25lbnRzfWApfTtcbiAgICAgICAgICBkb3RQcm9kID0gZG90UHJvZCArIHhWYWx1ZSAqIHdWYWx1ZTtgO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgYUNvbXBvbmVudHM7IGMrKykge1xuICAgICAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgICBsZXQgd1ZhbHVlJHtjfSA9ICR7dy5nZXRCeU9mZnNldChgJHt3LmluZGljZXNUb09mZnNldChgJHt3LnR5cGUuaW5kaWNlc30odTMyKHdSUGVybSksIHUzMih3Q1Blcm0pLCBpbnB1dENoYW5uZWwgKyAke2N9LCB3T3V0Q2hhbm5lbClgKX0gLyAke2JDb21wb25lbnRzfWApfTtcbiAgICAgICAgICAgIGRvdFByb2QgPSBkb3RQcm9kICsgeFZhbHVlWyR7Y31dICogd1ZhbHVlJHtjfTtgO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGNhbGNTdHI7XG4gICAgfTtcbiAgICBjb25zdCBjYWxjdWxhdGVSZW1haW5kZXIgPSAoKTogc3RyaW5nID0+IHtcbiAgICAgIGlmIChpbnB1dENoYW5uZWxzUmVtYWluZGVyID09PSAwKSB7XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIH1cbiAgICAgIGlmICghcGFja0lucHV0QXM0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgcGFja0lucHV0QXM0ICR7cGFja0lucHV0QXM0fSBpcyBub3QgdHJ1ZS5gKTtcbiAgICAgIH1cbiAgICAgIGxldCBjYWxjU3RyID0gJyc7XG4gICAgICBpZiAoYUNvbXBvbmVudHMgPT09IDEpIHtcbiAgICAgICAgY2FsY1N0ciArPSAnZG90UHJvZCA9IGRvdFByb2QnO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0Q2hhbm5lbHNSZW1haW5kZXI7IGkrKykge1xuICAgICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgICAgKyAke2R5LmdldEJ5T2Zmc2V0KGB4X29mZnNldCArICR7aX1gKX0gKiAke3cuZ2V0QnlPZmZzZXQoYHdfb2Zmc2V0ICsgJHtpfWApfWA7XG4gICAgICAgIH1cbiAgICAgICAgY2FsY1N0ciArPSAnOyc7XG4gICAgICB9IGVsc2UgaWYgKGFDb21wb25lbnRzID09PSAyKSB7XG4gICAgICAgIGlmIChpbnB1dENoYW5uZWxzUmVtYWluZGVyICE9PSAyKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGlucHV0Q2hhbm5lbHNSZW1haW5kZXIgJHtpbnB1dENoYW5uZWxzUmVtYWluZGVyfS5gKTtcbiAgICAgICAgfVxuICAgICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICBsZXQgeFZhbHVlID0gJHtkeS5nZXRCeU9mZnNldCgneF9vZmZzZXQnKX07XG4gICAgICAgICAgbGV0IHdWYWx1ZSA9ICR7dy5nZXRCeU9mZnNldCgnd19vZmZzZXQnKX07XG4gICAgICAgICAgZG90UHJvZCA9IGRvdFByb2QgKyBkb3QoeFZhbHVlLCB3VmFsdWUpO2A7XG4gICAgICB9XG4gICAgICByZXR1cm4gY2FsY1N0cjtcbiAgICB9O1xuICAgIGNvbnN0IGNvZGVTbmlwcGV0ID0gYFxuICAgICAgICAgICAgbGV0IG91dHB1dEluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoYGdsb2JhbF9pZHggKiAke2NvbXBvbmVudHN9YCl9O1xuICAgICAgICAgICAgbGV0IGJhdGNoID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0SW5kaWNlcycsIDApfTtcbiAgICAgICAgICAgIGxldCBkMSA9ICR7b3V0cHV0LmluZGljZXNHZXQoJ291dHB1dEluZGljZXMnLCBjaGFubmVsRGltKX07XG4gICAgICAgICAgICBsZXQgciA9ICR7b3V0cHV0LmluZGljZXNHZXQoJ291dHB1dEluZGljZXMnLCByb3dEaW0pfTtcbiAgICAgICAgICAgIGxldCBjID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0SW5kaWNlcycsIGNvbERpbSl9O1xuICAgICAgICAgICAgbGV0IGR5Q29ybmVyID0gdmVjMjxpMzI+KGkzMihyKSwgaTMyKGMpKSAtIHVuaWZvcm1zLnBhZHM7XG4gICAgICAgICAgICBsZXQgZHlSQ29ybmVyID0gZHlDb3JuZXIueDtcbiAgICAgICAgICAgIGxldCBkeUNDb3JuZXIgPSBkeUNvcm5lci55O1xuICAgICAgICAgICAgbGV0IGdyb3VwSWQgPSBkMSAvIHVuaWZvcm1zLm91dHB1dF9jaGFubmVsc19wZXJfZ3JvdXA7XG4gICAgICAgICAgICBsZXQgd091dENoYW5uZWwgPSBkMSAtIGdyb3VwSWQgKiB1bmlmb3Jtcy5vdXRwdXRfY2hhbm5lbHNfcGVyX2dyb3VwO1xuICAgICAgICAgICAgLy8gQ29udm9sdmUgZHkoPywgPywgZDIpIHdpdGggdyg6LCA6LCBkMSwgZDIpIHRvIGNvbXB1dGUgZHgoeFIsIHhDLCBkMSkuXG4gICAgICAgICAgICAvLyA/ID0gdG8gYmUgZGV0ZXJtaW5lZC4gOiA9IGFjcm9zcyBhbGwgdmFsdWVzIGluIHRoYXQgYXhpcy5cbiAgICAgICAgICAgIHZhciBkb3RQcm9kID0gJHtvdXRwdXQudHlwZS52YWx1ZX0oMC4wKTtcbiAgICAgICAgICAgIHZhciB3UjogdTMyID0gMDtcbiAgICAgICAgICAgIGlmICh1bmlmb3Jtcy5kaWxhdGlvbnMueCA9PSAxKSB7XG4gICAgICAgICAgICAgIC8vIE1pbmltdW0gd1IgPj0gMCB0aGF0IHNhdGlzZmllcyAoZHlSQ29ybmVyICsgd1IpICUgKHVuaWZvcm1zLnN0cmlkZXMueCkgPT0gMFxuICAgICAgICAgICAgICB3UiA9IHUzMigoKGR5UkNvcm5lciArIGkzMih1bmlmb3Jtcy5zdHJpZGVzLngpIC0gMSkgLyBpMzIodW5pZm9ybXMuc3RyaWRlcy54KSkgKiBpMzIodW5pZm9ybXMuc3RyaWRlcy54KSAtIGR5UkNvcm5lcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKDsgd1IgPCB1bmlmb3Jtcy5lZmZlY3RpdmVfZmlsdGVyX2RpbXMueDsgd1IgPSB3UiArIDEpIHtcbiAgICAgICAgICAgICAgaWYgKHdSICUgdW5pZm9ybXMuZGlsYXRpb25zLnggIT0gMCkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGxldCBkeVIgPSAoJHtkYXRhVHlwZX0oZHlSQ29ybmVyKSArICR7ZGF0YVR5cGV9KHdSKSkgLyAke2RhdGFUeXBlfSh1bmlmb3Jtcy5zdHJpZGVzWzBdKTtcbiAgICAgICAgICAgICAgbGV0IHdSUGVybSA9IHVuaWZvcm1zLmZpbHRlcl9kaW1zLnggLSAxIC0gd1IgLyB1bmlmb3Jtcy5kaWxhdGlvbnMueDtcbiAgICAgICAgICAgICAgaWYgKGR5UiA8IDAuMCB8fCBkeVIgPj0gJHtkYXRhVHlwZX0odW5pZm9ybXMuRHlfc2hhcGVbJHtyb3dEaW19XSkgfHwgZnJhY3QoZHlSKSA+IDAuMCB8fFxuICAgICAgICAgICAgICAgICAgd1JQZXJtIDwgMCkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGxldCBpZHlSOiB1MzIgPSB1MzIoZHlSKTtcbiAgICAgICAgICAgICAgdmFyIHdDOiB1MzIgPSAwO1xuICAgICAgICAgICAgICBpZiAodW5pZm9ybXMuZGlsYXRpb25zLnkgPT0gMSkge1xuICAgICAgICAgICAgICAgIC8vIE1pbmltdW0gd0MgPj0gMCB0aGF0IHNhdGlzZmllcyAoZHlDQ29ybmVyICsgd0MpICUgKHVuaWZvcm1zLnN0cmlkZXMueSkgPT0gMFxuICAgICAgICAgICAgICAgIHdDID0gdTMyKCgoZHlDQ29ybmVyICsgaTMyKHVuaWZvcm1zLnN0cmlkZXMueSkgLSAxKSAvIGkzMih1bmlmb3Jtcy5zdHJpZGVzLnkpKSAqIGkzMih1bmlmb3Jtcy5zdHJpZGVzLnkpIC0gZHlDQ29ybmVyKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBmb3IgKDsgd0MgPCB1bmlmb3Jtcy5lZmZlY3RpdmVfZmlsdGVyX2RpbXMueTsgd0MgPSB3QyArIDEpIHtcbiAgICAgICAgICAgICAgICBpZiAod0MgJSB1bmlmb3Jtcy5kaWxhdGlvbnMueSAhPSAwKSB7XG4gICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGR5QyA9ICgke2RhdGFUeXBlfShkeUNDb3JuZXIpICsgJHtkYXRhVHlwZX0od0MpKSAvICR7ZGF0YVR5cGV9KHVuaWZvcm1zLnN0cmlkZXMueSk7XG4gICAgICAgICAgICAgICAgbGV0IHdDUGVybSA9IHVuaWZvcm1zLmZpbHRlcl9kaW1zLnkgLSAxIC0gd0MgLyB1bmlmb3Jtcy5kaWxhdGlvbnMueTtcbiAgICAgICAgICAgICAgICBpZiAoZHlDIDwgMC4wIHx8IGR5QyA+PSAke2RhdGFUeXBlfSh1bmlmb3Jtcy5EeV9zaGFwZVske2NvbERpbX1dKSB8fFxuICAgICAgICAgICAgICAgICAgICBmcmFjdChkeUMpID4gMC4wIHx8IHdDUGVybSA8IDApIHtcbiAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgaWR5QzogdTMyID0gdTMyKGR5Qyk7XG4gICAgICAgICAgICAgICAgdmFyIGlucHV0Q2hhbm5lbCA9IGdyb3VwSWQgKiB1bmlmb3Jtcy5pbnB1dF9jaGFubmVsc19wZXJfZ3JvdXA7XG4gICAgICAgICAgICAgICAgJHtcbiAgICAgICAgICAgICAgICAgIHBhY2tJbnB1dEFzNFxuICAgICAgICAgICAgICAgICAgICA/IGBcbiAgICAgICAgICAgICAgICB2YXIgeF9vZmZzZXQgPSAke2R5LmluZGljZXNUb09mZnNldChgJHtkeS50eXBlLmluZGljZXN9KGJhdGNoLCBpZHlSLCBpZHlDLCBpbnB1dENoYW5uZWwpYCl9IC8gJHthQ29tcG9uZW50c307XG4gICAgICAgICAgICAgICAgdmFyIHdfb2Zmc2V0ID0gJHt3LmluZGljZXNUb09mZnNldChgJHt3LnR5cGUuaW5kaWNlc30od1JQZXJtLCB3Q1Blcm0sIGlucHV0Q2hhbm5lbCwgd091dENoYW5uZWwpYCl9IC8gJHtiQ29tcG9uZW50c307XG4gICAgICAgICAgICAgICAgICBgXG4gICAgICAgICAgICAgICAgICAgIDogJydcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgZDI6IHUzMiA9IDA7IGQyIDwgdW5pZm9ybXMuaW5wdXRfY2hhbm5lbHNfcGVyX2dyb3VwX2ludDsgZDIgPSBkMiArICR7cGFja0lucHV0QXM0ID8gNCA6IGFDb21wb25lbnRzfSkge1xuICAgICAgICAgICAgICAgICAgJHtjYWxjdWxhdGVSZXN1bHQoKX1cbiAgICAgICAgICAgICAgICAgIGlucHV0Q2hhbm5lbCA9IGlucHV0Q2hhbm5lbCArICR7cGFja0lucHV0QXM0ID8gNCA6IGFDb21wb25lbnRzfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJHtjYWxjdWxhdGVSZW1haW5kZXIoKX1cbiAgICAgICAgICAgICAgICB3QyA9IHdDICsgdW5pZm9ybXMuc3RyaWRlcy55IC0gMTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB3UiA9IHdSICsgdW5pZm9ybXMuc3RyaWRlc1swXSAtIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBkb3RQcm9kJHtoYXNCaWFzID8gYCArIGJpYXNbZDEgLyAke2NvbXBvbmVudHN9XWAgOiAnJ307XG4gICAgICAgICAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICd2YWx1ZScpfTtcbiAgICAgICAgICBgO1xuXG4gICAgcmV0dXJuIGBcbiAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKC4uLmlucHV0VmFyaWFibGVzLCBvdXRwdXQpfVxuICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfTtcbiAgICAke2NvZGVTbmlwcGV0fX1gO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0NvbnZUcmFuc3Bvc2UyRCcsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2F0dHJpYnV0ZXMuY2FjaGVLZXl9OyR7YUNvbXBvbmVudHN9JHtiQ29tcG9uZW50c30ke2NvbXBvbmVudHN9JHtwYWNrSW5wdXRBczR9JHtpbnB1dENoYW5uZWxzUmVtYWluZGVyfWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llcyxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IGRpc3BhdGNoWzBdLCB5OiBkaXNwYXRjaFsxXSwgejogZGlzcGF0Y2hbMl0gfSxcbiAgICAgIG91dHB1dHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGRpbXM6IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uID8gc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24ob3V0cHV0U2hhcGUpIDogb3V0cHV0U2hhcGUsXG4gICAgICAgICAgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0IH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVDb252VHJhbnNwb3NlMkRQcm9ncmFtSW5mbyB9IGZyb20gJy4vM3JkLXBhcnR5L2NvbnZfYmFja3Byb3Bfd2ViZ3B1JztcbmltcG9ydCB7IENvbnZBdHRyaWJ1dGVzIH0gZnJvbSAnLi9jb252JztcbmltcG9ydCB7IHBhcnNlSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyB9IGZyb20gJy4vZnVzZS11dGlscyc7XG5pbXBvcnQgeyBjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyB9IGZyb20gJy4vdHJhbnNwb3NlJztcblxuY29uc3QgY29tcHV0ZVRvdGFsUGFkID0gKFxuICBpbkRpbTogbnVtYmVyLFxuICBzdHJpZGU6IG51bWJlcixcbiAgYWRqOiBudW1iZXIsXG4gIGtlcm5lbDogbnVtYmVyLFxuICBkaWxhdGlvbjogbnVtYmVyLFxuICBvdXRTaXplOiBudW1iZXIsXG4pID0+IChpbkRpbSAtIDEpICogc3RyaWRlICsgYWRqICsgKGtlcm5lbCAtIDEpICogZGlsYXRpb24gKyAxIC0gb3V0U2l6ZTtcblxuY29uc3QgZGlzdHJpYnV0ZVBhZGRpbmcgPSAodG90YWxQYWQ6IG51bWJlciwgYXV0b1BhZDogc3RyaW5nLCBwYWRzOiBudW1iZXJbXSwgaGVhZDogbnVtYmVyLCB0YWlsOiBudW1iZXIpID0+IHtcbiAgY29uc3Qgc21hbGxQYWQgPSBNYXRoLmZsb29yKHRvdGFsUGFkIC8gMik7XG4gIGlmIChhdXRvUGFkID09PSAnU0FNRV9VUFBFUicpIHtcbiAgICBwYWRzW2hlYWRdID0gc21hbGxQYWQ7XG4gICAgcGFkc1t0YWlsXSA9IHRvdGFsUGFkIC0gc21hbGxQYWQ7XG4gIH0gZWxzZSBpZiAoYXV0b1BhZCA9PT0gJ1NBTUVfTE9XRVInKSB7XG4gICAgcGFkc1toZWFkXSA9IHRvdGFsUGFkIC0gc21hbGxQYWQ7XG4gICAgcGFkc1t0YWlsXSA9IHNtYWxsUGFkO1xuICB9XG59O1xuXG5jb25zdCBjYWxjdWxhdGVPdXRwdXRTaGFwZUFuZFBhZHMgPSAoXG4gIGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGRpbGF0aW9uczogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGF1dG9QYWQ6IHN0cmluZyxcbiAgZ3JvdXA6IG51bWJlcixcbiAgcGFkczogbnVtYmVyW10sXG4gIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICBpc0NoYW5uZWxMYXN0OiBib29sZWFuLFxuICBvdXRwdXRQYWRkaW5nOiBudW1iZXJbXSxcbiAgb3V0cHV0U2hhcGU6IG51bWJlcltdLFxuKSA9PiB7XG4gIGNvbnN0IHNwYXRpYWxSYW5rID0gaW5wdXRTaGFwZS5sZW5ndGggLSAyO1xuICBjb25zdCB1cGRhdGVPdXRwdXRTaGFwZSA9IG91dHB1dFNoYXBlLmxlbmd0aCA9PT0gMDtcbiAgaWYgKG91dHB1dFBhZGRpbmcubGVuZ3RoIDwgc3BhdGlhbFJhbmspIHtcbiAgICBvdXRwdXRQYWRkaW5nLnB1c2goLi4uQXJyYXkoc3BhdGlhbFJhbmsgLSBvdXRwdXRQYWRkaW5nLmxlbmd0aCkuZmlsbCgwKSk7XG4gIH1cbiAgY29uc3QgYmF0Y2hTaXplID0gaW5wdXRTaGFwZVswXTtcbiAgY29uc3Qgb3V0Q2hhbm5lbHMgPSBrZXJuZWxTaGFwZVtpc0NoYW5uZWxMYXN0ID8gMyA6IDFdICogZ3JvdXA7XG4gIGZvciAobGV0IGkgPSAwLCBqID0gaW5wdXRTaGFwZS5sZW5ndGggLSBzcGF0aWFsUmFuayAtIChpc0NoYW5uZWxMYXN0ID8gMSA6IDApOyBpIDwgc3BhdGlhbFJhbms7ICsraSwgKytqKSB7XG4gICAgY29uc3QgaW5TaXplID0gaW5wdXRTaGFwZVtqXTtcbiAgICBjb25zdCBvdXRTaXplID0gdXBkYXRlT3V0cHV0U2hhcGUgPyBpblNpemUgKiBzdHJpZGVzW2ldIDogb3V0cHV0U2hhcGVbaV07XG4gICAgY29uc3QgdG90YWxQYWQgPSBjb21wdXRlVG90YWxQYWQoaW5TaXplLCBzdHJpZGVzW2ldLCBwYWRzW2ldLCBrZXJuZWxTaGFwZVtqXSwgZGlsYXRpb25zW2ldLCBvdXRTaXplKTtcbiAgICBkaXN0cmlidXRlUGFkZGluZyh0b3RhbFBhZCwgYXV0b1BhZCwgcGFkcywgaSwgaSArIHNwYXRpYWxSYW5rKTtcbiAgICBpZiAodXBkYXRlT3V0cHV0U2hhcGUpIHtcbiAgICAgIG91dHB1dFNoYXBlLnB1c2goXG4gICAgICAgIHN0cmlkZXNbaV0gKiAoaW5TaXplIC0gMSkgK1xuICAgICAgICAgIG91dHB1dFBhZGRpbmdbaV0gK1xuICAgICAgICAgIChrZXJuZWxTaGFwZVtqXSAtIDEpICogZGlsYXRpb25zW2ldICtcbiAgICAgICAgICAxIC1cbiAgICAgICAgICBwYWRzW2ldIC1cbiAgICAgICAgICBwYWRzW2kgKyBzcGF0aWFsUmFua10sXG4gICAgICApO1xuICAgIH1cbiAgfVxuICBvdXRwdXRTaGFwZS5zcGxpY2UoMCwgMCwgYmF0Y2hTaXplKTtcbiAgb3V0cHV0U2hhcGUuc3BsaWNlKGlzQ2hhbm5lbExhc3QgPyAzIDogMSwgMCwgb3V0Q2hhbm5lbHMpO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBDb252VHJhbnNwb3NlQXR0cmlidXRlcyBleHRlbmRzIENvbnZBdHRyaWJ1dGVzIHtcbiAgcmVhZG9ubHkgb3V0cHV0UGFkZGluZzogcmVhZG9ubHkgbnVtYmVyW107XG4gIHJlYWRvbmx5IG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXTtcbn1cblxuY29uc3QgZ2V0QWRqdXN0ZWRDb252VHJhbnNwb3NlQXR0cmlidXRlcyA9IDxUIGV4dGVuZHMgQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXM+KFxuICBhdHRyaWJ1dGVzOiBULFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbik6IFQgPT4ge1xuICBjb25zdCBrZXJuZWxTaGFwZSA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGUuc2xpY2UoKTtcbiAgLy8gaWYga2VybmVsU2hhcGUgaXMgbm90IHNwZWNpZmllZCBpbiB0aGUgYXR0cmlidXRlcyBvZiB0aGlzIG9wLCBpbmZlciBpdCBmcm9tIHRoZSB3ZWlnaHQgdGVuc29yIGRpbXNcbiAgaWYgKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoID09PSAwIHx8IGF0dHJpYnV0ZXMua2VybmVsU2hhcGUucmVkdWNlKChhLCBiKSA9PiBhICogYiwgMSkgPT09IDApIHtcbiAgICBrZXJuZWxTaGFwZS5sZW5ndGggPSAwO1xuICAgIGZvciAobGV0IGkgPSAyOyBpIDwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIGtlcm5lbFNoYXBlLnB1c2goaW5wdXRzWzFdLmRpbXNbaV0pO1xuICAgIH1cbiAgfVxuICBjb25zdCBpc0NoYW5uZWxzTGFzdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQyc7XG4gIGtlcm5lbFNoYXBlLnNwbGljZSgwLCAwLCBpbnB1dHNbMV0uZGltc1swXSk7XG4gIGtlcm5lbFNoYXBlLnNwbGljZShpc0NoYW5uZWxzTGFzdCA/IDMgOiAxLCAwLCBpbnB1dHNbMV0uZGltc1sxXSk7XG5cbiAgY29uc3QgcGFkcyA9IGF0dHJpYnV0ZXMucGFkcy5zbGljZSgpO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGF0dHJpYnV0ZXMub3V0cHV0U2hhcGUuc2xpY2UoKTtcbiAgY29uc3Qgb3V0cHV0UGFkZGluZyA9IGF0dHJpYnV0ZXMub3V0cHV0UGFkZGluZy5zbGljZSgpO1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGxldCBkaWxhdGlvbnMgPSBhdHRyaWJ1dGVzLmRpbGF0aW9ucy5zbGljZSgpO1xuICBpZiAoZGlsYXRpb25zLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApID09PSAwKSB7XG4gICAgY29uc3Qgc3BhdGlhbFJhbmsgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAyO1xuICAgIGRpbGF0aW9ucyA9IG5ldyBBcnJheShzcGF0aWFsUmFuaykuZmlsbCgxKTtcbiAgfVxuICBsZXQgc3RyaWRlcyA9IGF0dHJpYnV0ZXMuc3RyaWRlcy5zbGljZSgpO1xuICBpZiAoc3RyaWRlcy5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKSA9PT0gMCkge1xuICAgIGNvbnN0IHNwYXRpYWxSYW5rID0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMjtcbiAgICBzdHJpZGVzID0gbmV3IEFycmF5KHNwYXRpYWxSYW5rKS5maWxsKDEpO1xuICB9XG4gIC8vIElmIG91dHB1dFNoYXBlIGlzIG5vdCBzcGVjaWZpZWQgaW4gdGhlIGF0dHJpYnV0ZXMgb2YgdGhpcyBvcCwgaW5mZXIgaXQgZnJvbSB0aGUgcGFyYW1ldGVyc1xuICAvLyBTaW1pbGFybHksIGF1dG9tYXRpY2FsbHkgaW5mZXIgcGFkcyBpZiBub3Qgc3BlY2lmaWVkXG4gIGNhbGN1bGF0ZU91dHB1dFNoYXBlQW5kUGFkcyhcbiAgICBpbnB1dFNoYXBlLFxuICAgIGtlcm5lbFNoYXBlLFxuICAgIGRpbGF0aW9ucyxcbiAgICBhdHRyaWJ1dGVzLmF1dG9QYWQsXG4gICAgYXR0cmlidXRlcy5ncm91cCxcbiAgICBwYWRzLFxuICAgIHN0cmlkZXMsXG4gICAgaXNDaGFubmVsc0xhc3QsXG4gICAgb3V0cHV0UGFkZGluZyxcbiAgICBvdXRwdXRTaGFwZSxcbiAgKTtcblxuICAvLyBhbHdheXMgcmV0dXJuIGEgbmV3IG9iamVjdCBzbyBkb2VzIG5vdCBtb2RpZnkgdGhlIG9yaWdpbmFsIGF0dHJpYnV0ZXNcbiAgY29uc3QgbmV3QXR0cmlidXRlczogVCA9IE9iamVjdC5hc3NpZ24oe30sIGF0dHJpYnV0ZXMpO1xuICBPYmplY3QuYXNzaWduKG5ld0F0dHJpYnV0ZXMsIHsga2VybmVsU2hhcGUsIHBhZHMsIG91dHB1dFBhZGRpbmcsIG91dHB1dFNoYXBlLCBkaWxhdGlvbnMsIHN0cmlkZXMgfSk7XG4gIHJldHVybiBuZXdBdHRyaWJ1dGVzO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBDb252VHJhbnNwb3NlQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGFjdGl2YXRpb25BdHRyaWJ1dGVzID0gcGFyc2VJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpO1xuICAvLyBUT0RPIDogTWFrZSB0aGlzIGdlbmVyaWMgZW5vdWdoIHRvIGNvbXB1dGUgZGVmYXVsdCBhdHRyaWJ1dGVzIGZvciBtdWx0aS1kaW1lbnNpb25hbCBjb252XG4gIGNvbnN0IGZvcm1hdCA9IGF0dHJpYnV0ZXMuZm9ybWF0IGFzICdOSFdDJyB8ICdOQ0hXJztcbiAgY29uc3QgYXV0b1BhZCA9IFsnTk9UU0VUJywgJ1ZBTElEJywgJ1NBTUVfVVBQRVInLCAnU0FNRV9MT1dFUiddW1xuICAgIHR5cGVvZiBhdHRyaWJ1dGVzLmF1dG9QYWQgPT0gJ3VuZGVmaW5lZCcgPyAwIDogKGF0dHJpYnV0ZXMuYXV0b1BhZCBhcyBudW1iZXIpXG4gIF07XG4gIGNvbnN0IGRpbGF0aW9ucyA9IGF0dHJpYnV0ZXMuZGlsYXRpb25zIGFzIFtudW1iZXIsIG51bWJlcl07XG4gIGNvbnN0IGdyb3VwID0gYXR0cmlidXRlcy5ncm91cCBhcyBudW1iZXI7XG4gIGNvbnN0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdO1xuICBjb25zdCBwYWRzID0gYXR0cmlidXRlcy5wYWRzIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICBjb25zdCBzdHJpZGVzID0gYXR0cmlidXRlcy5zdHJpZGVzIGFzIFtudW1iZXIsIG51bWJlcl07XG4gIGNvbnN0IHdJc0NvbnN0ID0gKGF0dHJpYnV0ZXMud0lzQ29uc3QgYXMgKCkgPT4gYm9vbGVhbikoKTtcbiAgY29uc3Qgb3V0cHV0UGFkZGluZyA9IGF0dHJpYnV0ZXMub3V0cHV0UGFkZGluZyBhcyBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBhdHRyaWJ1dGVzLm91dHB1dFNoYXBlIGFzIFtudW1iZXIsIG51bWJlcl07XG4gIHJldHVybiB7XG4gICAgYXV0b1BhZCxcbiAgICBmb3JtYXQsXG4gICAgZGlsYXRpb25zLFxuICAgIGdyb3VwLFxuICAgIGtlcm5lbFNoYXBlLFxuICAgIG91dHB1dFBhZGRpbmcsXG4gICAgb3V0cHV0U2hhcGUsXG4gICAgcGFkcyxcbiAgICBzdHJpZGVzLFxuICAgIHdJc0NvbnN0LFxuICAgIC4uLmFjdGl2YXRpb25BdHRyaWJ1dGVzLFxuICAgIGNhY2hlS2V5OiBgJHthdHRyaWJ1dGVzLmZvcm1hdH07JHthY3RpdmF0aW9uQXR0cmlidXRlcy5hY3RpdmF0aW9ufTtgLFxuICB9O1xufTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIC8vIFJlZmVyIHRvIHRoZSBiZWxvdyBsaW5rIGZvciBhbGwgaW5wdXQgY2hlY2tzXG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9vbm54L29ubngvYmxvYi9tYWluL2RvY3MvT3BlcmF0b3JzLm1kI0NvbnZUcmFuc3Bvc2VcbiAgaWYgKCFpbnB1dHMgfHwgKGlucHV0cy5sZW5ndGggIT09IDIgJiYgaW5wdXRzLmxlbmd0aCAhPT0gMykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbnYgcmVxdWlyZXMgMiBvciAzIGlucHV0cycpO1xuICB9XG5cbiAgLy8gVE9ETyA6IE5lZWQgdG8gYWRkIHN1cHBvcnQgZm9yIG11bHRpLWRpbWVuc2lvbmFsIGNvbnZcbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gNCAmJiBpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2N1cnJlbnRseSBvbmx5IHN1cHBvcnQgMi1kaW1lbnNpb25hbCBjb252Jyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoICE9PSBpbnB1dHNbMV0uZGltcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ZpbHRlciBkb2VzIG5vdCBoYXZlIHNhbWUgZGltZW5zaW9uIGFzIGlucHV0Jyk7XG4gIH1cblxuICAvLyBGSUxURVJfSU5fQ0hBTk5FTCBzaG91bGQgYmUgZXF1YWwgdG8gREFUQV9DSEFOTkVMXG4gIGNvbnN0IGRhdGFDaGFubmVsID0gaW5wdXRzWzBdLmRpbXNbYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJyA/IGlucHV0c1swXS5kaW1zLmxlbmd0aCAtIDEgOiAxXTtcbiAgY29uc3QgZmlsdGVySW5DaGFubmVsID0gaW5wdXRzWzFdLmRpbXNbMF07XG4gIGlmIChkYXRhQ2hhbm5lbCAhPT0gZmlsdGVySW5DaGFubmVsKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGSUxURVJfSU5fQ0hBTk5FTCBzaG91bGQgYmUgZXF1YWwgdG8gREFUQV9DSEFOTkVMJyk7XG4gIH1cblxuICBjb25zdCBmZWF0dXJlTWFwcyA9IGlucHV0c1sxXS5kaW1zWzFdICogYXR0cmlidXRlcy5ncm91cDtcblxuICAvLyBpZiBiaWFzIGlzIHByb3ZpZGVkIGl0IHNob3VsZCBiZSAxRCBhbmQgdGhlIG51bWJlciBvZiBlbGVtZW50cyBzaG91bGQgYmUgZXF1YWwgdG8gdGhlIG51bWJlciBvZiBmZWF0dXJlIG1hcHNcbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMgJiYgKGlucHV0c1syXS5kaW1zLmxlbmd0aCAhPT0gMSB8fCBpbnB1dHNbMl0uZGltc1swXSAhPT0gZmVhdHVyZU1hcHMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGJpYXMnKTtcbiAgfVxuXG4gIGNvbnN0IHNwYXRpYWxSYW5rID0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMjtcbiAgY29uc3QgZGlsYXRpb25zU2V0ID0gYXR0cmlidXRlcy5kaWxhdGlvbnMucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCkgPiAwO1xuICAvLyB3cm9uZyBkaWxhdGlvbnMgZGltZW5zaW9uXG4gIGlmIChkaWxhdGlvbnNTZXQgJiYgYXR0cmlidXRlcy5kaWxhdGlvbnMubGVuZ3RoICE9PSBzcGF0aWFsUmFuaykge1xuICAgIHRocm93IG5ldyBFcnJvcihgZGlsYXRpb25zIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rfURgKTtcbiAgfVxuXG4gIGNvbnN0IHN0cmlkZXNTZXQgPSBhdHRyaWJ1dGVzLnN0cmlkZXMucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCkgPiAwO1xuICAvLyBXcm9uZyBzdHJpZGVzIGRpbWVuc2lvblxuICBpZiAoc3RyaWRlc1NldCAmJiBhdHRyaWJ1dGVzLnN0cmlkZXMubGVuZ3RoICE9PSBzcGF0aWFsUmFuaykge1xuICAgIHRocm93IG5ldyBFcnJvcihgc3RyaWRlcyBzaG91bGQgYmUgJHtzcGF0aWFsUmFua31EYCk7XG4gIH1cblxuICAvLyBXcm9uZyBwYWRzIGRpbWVuc2lvblxuICBjb25zdCBwYWRzU2V0ID0gYXR0cmlidXRlcy5wYWRzLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApID4gMDtcbiAgaWYgKHBhZHNTZXQgJiYgYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAhPT0gc3BhdGlhbFJhbmsgKiAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBwYWRzIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rICogMn1EYCk7XG4gIH1cblxuICAvLyBXcm9uZyBvdXRwdXQgcGFkZGluZyBkaW1lbnNpb25cbiAgaWYgKGF0dHJpYnV0ZXMub3V0cHV0UGFkZGluZy5sZW5ndGggIT09IHNwYXRpYWxSYW5rICYmIGF0dHJpYnV0ZXMub3V0cHV0UGFkZGluZy5sZW5ndGggIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYG91dHB1dF9wYWRkaW5nIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rfURgKTtcbiAgfVxuXG4gIC8vIGlmIGtlcm5lbFNoYXBlIGlzIHNwZWNpZmllZCwgaXQncyBkYXRhIGxlbmd0aCBtdXN0IGJlIDIgbGVzcyB0aGFuIGRpbXMgbGVuZ3RoIG9mIHRoZSB3ZWlnaHRzIHRlbnNvclxuICAvLyAodGhlIGZpcnN0IDIgZGltcyBhcmUgYmF0Y2hfc2l6ZSBhbmQgY2hhbm5lbHMpXG4gIGNvbnN0IGtlcm5lbFNoYXBlU2V0ID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKSA+IDA7XG4gIGlmIChcbiAgICBrZXJuZWxTaGFwZVNldCAmJlxuICAgIGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoICE9PSAwICYmXG4gICAgYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggIT09IGlucHV0c1sxXS5kaW1zLmxlbmd0aCAtIDJcbiAgKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGtlcm5lbCBzaGFwZScpO1xuICB9XG5cbiAgLy8gYXMgd2l0aCBrZXJuZWxTaGFwZSwgbXVzdCBoYXZlIHNhbWUgbnVtYmVyIG9mIHNwYXRpYWwgZGltcyBhcyBpbnB1dFxuICBpZiAoYXR0cmlidXRlcy5vdXRwdXRTaGFwZS5sZW5ndGggIT09IDAgJiYgYXR0cmlidXRlcy5vdXRwdXRTaGFwZS5sZW5ndGggIT09IGlucHV0c1swXS5kaW1zLmxlbmd0aCAtIDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgb3V0cHV0IHNoYXBlJyk7XG4gIH1cbn07XG5cbmNvbnN0IGNvbnZUcmFuc3Bvc2UyZCA9IChcbiAgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBDb252VHJhbnNwb3NlQXR0cmlidXRlcyxcbiAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24/OiAoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKSA9PiBudW1iZXJbXSxcbik6IHZvaWQgPT4ge1xuICAvLyBTVEVQLjE6IHRyYW5zcG9zZSB3ZWlnaHRcbiAgY29uc3QgdHJhbnNwb3NlZFdlaWdodCA9XG4gICAgKGNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCBhcyBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkKSA/P1xuICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhpbnB1dHNbMV0sIFsyLCAzLCAwLCAxXSksIHtcbiAgICAgIGlucHV0czogWzFdLFxuICAgICAgb3V0cHV0czogW2F0dHJpYnV0ZXMud0lzQ29uc3QgPyAtMiA6IC0xXSxcbiAgICB9KVswXTtcbiAgaWYgKGF0dHJpYnV0ZXMud0lzQ29uc3QgJiYgIWNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCkge1xuICAgIGNvbnRleHQua2VybmVsQ3VzdG9tRGF0YS53VCA9IHRyYW5zcG9zZWRXZWlnaHQ7XG4gIH1cblxuICAvLyBTVEVQLjI6IHByZXBhcmUgcmVzaGFwZWQgaW5wdXRzXG4gIGNvbnN0IGNvbnZUcmFuc3Bvc2VJbnB1dHMgPSBbaW5wdXRzWzBdLCB0cmFuc3Bvc2VkV2VpZ2h0XTtcbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMpIHtcbiAgICBjb252VHJhbnNwb3NlSW5wdXRzLnB1c2goaW5wdXRzWzJdKTtcbiAgfVxuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlQ29udlRyYW5zcG9zZTJEUHJvZ3JhbUluZm8oY29udlRyYW5zcG9zZUlucHV0cywgYXR0cmlidXRlcywgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24pLCB7XG4gICAgaW5wdXRzOiBjb252VHJhbnNwb3NlSW5wdXRzLFxuICB9KTtcbn07XG5cbmNvbnN0IGNvbnZUcmFuc3Bvc2UxZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgLy8gZXh0ZW5kIHRoZSBpbnB1dCB0byAyRCBieSBhZGRpbmcgSCBkaW1lbnNpb25cbiAgY29uc3QgaXNDaGFubmVsTGFzdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQyc7XG5cbiAgY29uc3QgaW5wdXRzID0gW1xuICAgIGNvbnRleHQuaW5wdXRzWzBdLnJlc2hhcGUoXG4gICAgICBpc0NoYW5uZWxMYXN0XG4gICAgICAgID8gLy8gW04sIFcsIENdIC0+IFtOLCBIPTEsIFcsIENdXG4gICAgICAgICAgW2NvbnRleHQuaW5wdXRzWzBdLmRpbXNbMF0sIDEsIGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMV0sIGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMl1dXG4gICAgICAgIDogLy8gW04sIEMsIFddIC0+IFtOLCBDLCBIPTEsIFddXG4gICAgICAgICAgW2NvbnRleHQuaW5wdXRzWzBdLmRpbXNbMF0sIGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMV0sIDEsIGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMl1dLFxuICAgICksXG4gICAgLy9bRklMVEVSX09VVF9DSEFOTkVMLCBGSUxURVJfSU5fQ0hBTk5FTCwga1ddIC0+IFtGSUxURVJfT1VUX0NIQU5ORUwsIEZJTFRFUl9JTl9DSEFOTkVMLCBrSD0xLCBrV11cbiAgICBjb250ZXh0LmlucHV0c1sxXS5yZXNoYXBlKFtjb250ZXh0LmlucHV0c1sxXS5kaW1zWzBdLCBjb250ZXh0LmlucHV0c1sxXS5kaW1zWzFdLCAxLCBjb250ZXh0LmlucHV0c1sxXS5kaW1zWzJdXSksXG4gIF07XG4gIGlmIChjb250ZXh0LmlucHV0cy5sZW5ndGggPT09IDMpIHtcbiAgICBpbnB1dHMucHVzaChjb250ZXh0LmlucHV0c1syXSk7XG4gIH1cbiAgbGV0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZTtcbiAgaWYgKGtlcm5lbFNoYXBlLmxlbmd0aCA9PT0gMCB8fCBrZXJuZWxTaGFwZVswXSA9PT0gMCkge1xuICAgIGtlcm5lbFNoYXBlID0gW2NvbnRleHQuaW5wdXRzWzFdLmRpbXNbMl1dO1xuICB9XG4gIGxldCBkaWxhdGlvbnMgPSBhdHRyaWJ1dGVzLmRpbGF0aW9ucztcbiAgaWYgKGRpbGF0aW9ucy5sZW5ndGggPT09IDAgfHwgZGlsYXRpb25zWzBdID09PSAwKSB7XG4gICAgZGlsYXRpb25zID0gWzFdO1xuICB9XG4gIGxldCBzdHJpZGVzID0gYXR0cmlidXRlcy5zdHJpZGVzO1xuICBpZiAoc3RyaWRlcy5sZW5ndGggPT09IDAgfHwgc3RyaWRlc1swXSA9PT0gMCkge1xuICAgIHN0cmlkZXMgPSBbMV07XG4gIH1cbiAgbGV0IHBhZHMgPSBhdHRyaWJ1dGVzLnBhZHM7XG4gIGlmIChwYWRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHBhZHMgPSBbMCwgMF07XG4gIH1cbiAgcGFkcyA9IFswLCBwYWRzWzBdLCAwLCBwYWRzWzFdXTtcbiAgc3RyaWRlcyA9IFsxXS5jb25jYXQoc3RyaWRlcyk7XG4gIGRpbGF0aW9ucyA9IFsxXS5jb25jYXQoZGlsYXRpb25zKTtcbiAga2VybmVsU2hhcGUgPSBbMV0uY29uY2F0KGtlcm5lbFNoYXBlKTtcbiAgbGV0IG91dHB1dFBhZGRpbmcgPSBhdHRyaWJ1dGVzLm91dHB1dFBhZGRpbmc7XG4gIG91dHB1dFBhZGRpbmcgPSBbMF0uY29uY2F0KG91dHB1dFBhZGRpbmcpO1xuICBjb25zdCBhZGp1c3RlZEF0dHJpYnV0ZXMgPSBnZXRBZGp1c3RlZENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzKFxuICAgIHsgLi4uYXR0cmlidXRlcywgcGFkcywgc3RyaWRlcywgZGlsYXRpb25zLCBrZXJuZWxTaGFwZSwgb3V0cHV0UGFkZGluZyB9LFxuICAgIGlucHV0cyxcbiAgKTtcblxuICBjb252VHJhbnNwb3NlMmQoY29udGV4dCwgaW5wdXRzLCBhZGp1c3RlZEF0dHJpYnV0ZXMsIChvdXRwdXRTaGFwZSkgPT5cbiAgICBpc0NoYW5uZWxMYXN0ID8gW291dHB1dFNoYXBlWzBdLCBvdXRwdXRTaGFwZVsyXSwgb3V0cHV0U2hhcGVbM11dIDogW291dHB1dFNoYXBlWzBdLCBvdXRwdXRTaGFwZVsxXSwgb3V0cHV0U2hhcGVbM11dLFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGNvbnZUcmFuc3Bvc2UgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgaWYgKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMubGVuZ3RoID09PSAzKSB7XG4gICAgY29udlRyYW5zcG9zZTFkKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IGFkanVzdGVkQXR0cmlidXRlcyA9IGdldEFkanVzdGVkQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMoYXR0cmlidXRlcywgY29udGV4dC5pbnB1dHMpO1xuICAgIGNvbnZUcmFuc3Bvc2UyZChjb250ZXh0LCBjb250ZXh0LmlucHV0cywgYWRqdXN0ZWRBdHRyaWJ1dGVzKTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBnZXRFbGVtZW50QXQsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3VtU3VtQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGV4Y2x1c2l2ZTogYm9vbGVhbjtcbiAgcmVhZG9ubHkgcmV2ZXJzZTogYm9vbGVhbjtcbn1cbmNvbnN0IGNyZWF0ZUN1bXN1bVByb2dyYW1JbmZvID0gKFxuICBpbnB1dFR5cGU6IG51bWJlcixcbiAgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGF4aXNJbnB1dDogVGVuc29yVmlldyxcbiAgYXR0cmlidXRlczogQ3VtU3VtQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKGlucHV0U2hhcGUpOyAvLyBvdXRwdXRTaGFwZSBpcyBzYW1lIGFzIGlucHV0U2hhcGUuXG4gIGNvbnN0IHJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aDsgLy8gaW5wdXQvb3V0cHV0IHJhbmtcbiAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGlucHV0VHlwZSwgcmFuayk7XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dFR5cGUsIHJhbmspO1xuICBjb25zdCBheGlzVmFsdWUgPVxuICAgIGF4aXNJbnB1dC5kYXRhVHlwZSA9PT0gRGF0YVR5cGUuaW50MzIgPyBheGlzSW5wdXQuZ2V0SW50MzJBcnJheSgpWzBdIDogTnVtYmVyKGF4aXNJbnB1dC5nZXRCaWdJbnQ2NEFycmF5KClbMF0pO1xuICBjb25zdCBheGlzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4aXMoYXhpc1ZhbHVlLCByYW5rKTtcbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgaW5kZXggPSBgIGkzMigke2lucHV0LmluZGljZXNHZXQoJ2lucHV0SW5kaWNlcycsICd1bmlmb3Jtcy5heGlzJyl9KSBgO1xuICAgIGNvbnN0IG1heCA9IGdldEVsZW1lbnRBdCgndW5pZm9ybXMuaW5wdXRfc2hhcGUnLCAndW5pZm9ybXMuYXhpcycsIHJhbmspO1xuICAgIGNvbnN0IGxvd2VyTGltaXQgPSBhdHRyaWJ1dGVzLnJldmVyc2UgPyBpbmRleCArIChhdHRyaWJ1dGVzLmV4Y2x1c2l2ZSA/ICcgKyAxJyA6ICcnKSA6ICcwJztcbiAgICBjb25zdCB1cHBlckxpbWl0ID0gYXR0cmlidXRlcy5yZXZlcnNlID8gbWF4IDogaW5kZXggKyAoYXR0cmlidXRlcy5leGNsdXNpdmUgPyAnJyA6ICcgKyAxJyk7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgICAgICAgICAke3NoYWRlckhlbHBlclxuICAgICAgICAgICAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0U2l6ZScsICd1MzInKVxuICAgICAgICAgICAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnYXhpcycsICd1MzInKVxuICAgICAgICAgICAgICAgICAgLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIG91dHB1dCl9XG4gICAgICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICAgICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRTaXplJyl9XG4gICAgICAgICAgICAgICAgICB2YXIgaW5wdXRJbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgICAgICAgICAgICAgICAgdmFyIHN1bSA9ICR7b3V0cHV0LnR5cGUudmFsdWV9KDApO1xuICAgICAgICAgICAgICAgICAgbGV0IGZpcnN0IDogaTMyID0gJHtsb3dlckxpbWl0fTtcbiAgICAgICAgICAgICAgICAgIGxldCBsYXN0IDogaTMyID0gJHt1cHBlckxpbWl0fTtcbiAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgOiBpMzIgPSBmaXJzdDsgaSA8IGxhc3Q7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAke2lucHV0LmluZGljZXNTZXQoJ2lucHV0SW5kaWNlcycsICd1bmlmb3Jtcy5heGlzJywgJ3UzMihpKScpfTtcbiAgICAgICAgICAgICAgICAgICAgc3VtID0gc3VtICsgJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0SW5kaWNlcycpfTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3N1bScpfTtcbiAgICAgICAgICAgICAgICB9YDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQ3VtU3VtJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5LCBpbnB1dERlcGVuZGVuY2llczogWydyYW5rJ10gfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogaW5wdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0VHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYXhpcyB9LFxuICAgICAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dFNoYXBlLCBpbnB1dFNoYXBlKSxcbiAgICAgIF0sXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGN1bXN1bSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQ3VtU3VtQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBpbnB1dFNoYXBlID0gY29udGV4dC5pbnB1dHNbMF0uZGltcztcbiAgY29uc3QgaW5wdXRUeXBlID0gY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGU7XG4gIGNvbnN0IGF4aXMgPSBjb250ZXh0LmlucHV0c1sxXTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUN1bXN1bVByb2dyYW1JbmZvKGlucHV0VHlwZSwgaW5wdXRTaGFwZSwgYXhpcywgYXR0cmlidXRlcyksIHsgaW5wdXRzOiBbMF0gfSk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VDdW1TdW1BdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogQ3VtU3VtQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGV4Y2x1c2l2ZSA9IChhdHRyaWJ1dGVzLmV4Y2x1c2l2ZSBhcyBudW1iZXIpID09PSAxO1xuICBjb25zdCByZXZlcnNlID0gKGF0dHJpYnV0ZXMucmV2ZXJzZSBhcyBudW1iZXIpID09PSAxO1xuICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgZXhjbHVzaXZlLCByZXZlcnNlIH0pO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBJbmRpY2VzSGVscGVyLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIEZvcm1hdEF0dHJpYnV0ZXMge1xuICByZWFkb25seSBmb3JtYXQ6ICdOSFdDJyB8ICdOQ0hXJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEZXB0aFRvU3BhY2VBdHRyaWJ1dGVzIGV4dGVuZHMgRm9ybWF0QXR0cmlidXRlcywgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYmxvY2tzaXplOiBudW1iZXI7XG4gIHJlYWRvbmx5IG1vZGU6IHN0cmluZztcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignRGVwdGhUb1NwYWNlIHJlcXVpcmVzIDEgaW5wdXQuJyk7XG4gIH1cbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgIHRocm93IG5ldyBFcnJvcignRGVwdGhUb1NwYWNlIHJlcXVpcmVzIDREIGlucHV0LicpO1xuICB9XG59O1xuXG5jb25zdCBwZXJtRnVuY3Rpb25Cb2R5ID0gKHBlcm06IG51bWJlcltdLCByYW5rOiBudW1iZXIsIGlucHV0OiBJbmRpY2VzSGVscGVyLCBvdXRwdXQ6IEluZGljZXNIZWxwZXIpOiBzdHJpbmcgPT4ge1xuICBjb25zdCByZXZlcnNlRnVuYyA9IFtdO1xuICByZXZlcnNlRnVuYy5wdXNoKGBmbiBwZXJtKGk6ICR7b3V0cHV0LnR5cGUuaW5kaWNlc30pIC0+ICR7aW5wdXQudHlwZS5pbmRpY2VzfSB7XG4gICAgdmFyIGE6ICR7aW5wdXQudHlwZS5pbmRpY2VzfTtgKTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCByYW5rOyArK2kpIHtcbiAgICByZXZlcnNlRnVuYy5wdXNoKGlucHV0LmluZGljZXNTZXQoJ2EnLCBwZXJtW2ldLCBgaVske2l9XWApKTtcbiAgfVxuICByZXZlcnNlRnVuYy5wdXNoKCdyZXR1cm4gYTt9Jyk7XG4gIHJldHVybiByZXZlcnNlRnVuYy5qb2luKCdcXG4nKTtcbn07XG5cbmNvbnN0IGNyZWF0ZURlcHRoVG9TcGFjZVByb2dyYW1JbmZvID0gKGlucHV0VGVuc29yOiBUZW5zb3JWaWV3LCBhdHRyaWJ1dGVzOiBEZXB0aFRvU3BhY2VBdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8gPT4ge1xuICBsZXQgbjogbnVtYmVyLCBoOiBudW1iZXIsIHc6IG51bWJlciwgYzogbnVtYmVyO1xuICBsZXQgc2hhcGU6IG51bWJlcltdO1xuICBsZXQgcGVybTogbnVtYmVyW107XG4gIGNvbnN0IGlzQ2hhbm5lbExhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuICBjb25zdCBibG9ja3NpemUgPSBhdHRyaWJ1dGVzLmJsb2Nrc2l6ZTtcbiAgY29uc3QgaXNEQ1Jtb2RlID0gYXR0cmlidXRlcy5tb2RlID09PSAnRENSJztcbiAgaWYgKGlzQ2hhbm5lbExhc3QpIHtcbiAgICBbbiwgaCwgdywgY10gPSBpbnB1dFRlbnNvci5kaW1zO1xuICAgIHNoYXBlID0gaXNEQ1Jtb2RlXG4gICAgICA/IFtuLCBoLCB3LCBibG9ja3NpemUsIGJsb2Nrc2l6ZSwgYyAvIGJsb2Nrc2l6ZSAqKiAyXVxuICAgICAgOiBbbiwgaCwgdywgYyAvIGJsb2Nrc2l6ZSAqKiAyLCBibG9ja3NpemUsIGJsb2Nrc2l6ZV07XG4gICAgcGVybSA9IGlzRENSbW9kZSA/IFswLCAxLCAzLCAyLCA0LCA1XSA6IFswLCAxLCA0LCAyLCA1LCAzXTtcbiAgfSBlbHNlIHtcbiAgICBbbiwgaCwgdywgY10gPSBbaW5wdXRUZW5zb3IuZGltc1swXSwgaW5wdXRUZW5zb3IuZGltc1syXSwgaW5wdXRUZW5zb3IuZGltc1szXSwgaW5wdXRUZW5zb3IuZGltc1sxXV07XG4gICAgc2hhcGUgPSBpc0RDUm1vZGVcbiAgICAgID8gW24sIGJsb2Nrc2l6ZSwgYmxvY2tzaXplLCBjIC8gYmxvY2tzaXplICoqIDIsIGgsIHddXG4gICAgICA6IFtuLCBjIC8gYmxvY2tzaXplICoqIDIsIGJsb2Nrc2l6ZSwgYmxvY2tzaXplLCBoLCB3XTtcbiAgICBwZXJtID0gaXNEQ1Jtb2RlID8gWzAsIDMsIDQsIDEsIDUsIDJdIDogWzAsIDEsIDQsIDIsIDUsIDNdO1xuICB9XG4gIGNvbnN0IHJlc2hhcGVkSW5wdXRUZW5zb3IgPSBpbnB1dFRlbnNvci5yZXNoYXBlKHNoYXBlKTtcbiAgY29uc3QgcmVzaGFwZWRJbnB1dFJhbmsgPSByZXNoYXBlZElucHV0VGVuc29yLmRpbXMubGVuZ3RoO1xuICBjb25zdCBpbnB1dERhdGFUeXBlID0gaW5wdXRUZW5zb3IuZGF0YVR5cGU7XG5cbiAgY29uc3QgcmVzaGFwZWRJbnB1dCA9IGlucHV0VmFyaWFibGUoJ2EnLCBpbnB1dERhdGFUeXBlLCByZXNoYXBlZElucHV0UmFuayk7XG4gIGNvbnN0IHBlcm1lZE91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dERhdGFUeXBlLCByZXNoYXBlZElucHV0UmFuayk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0X3NpemUnLCAndTMyJykuZGVjbGFyZVZhcmlhYmxlcyhyZXNoYXBlZElucHV0LCBwZXJtZWRPdXRwdXQpfVxuXG4gICR7cGVybUZ1bmN0aW9uQm9keShwZXJtLCByZXNoYXBlZElucHV0UmFuaywgcmVzaGFwZWRJbnB1dCwgcGVybWVkT3V0cHV0KX1cblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuXG4gICAgbGV0IGluZGljZXMgPSAke3Blcm1lZE91dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgbGV0IGFJbmRpY2VzID0gcGVybShpbmRpY2VzKTtcblxuICAgICR7cGVybWVkT3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgcmVzaGFwZWRJbnB1dC5nZXRCeUluZGljZXMoJ2FJbmRpY2VzJykpfVxuICB9YDtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdEZXB0aFRvU3BhY2UnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHtpbnB1dFRlbnNvci5kaW1zfTske2F0dHJpYnV0ZXMuYmxvY2tzaXplfTske2F0dHJpYnV0ZXMubW9kZX1gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuayddLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKGlucHV0cykgPT4ge1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpc0NoYW5uZWxMYXN0XG4gICAgICAgID8gW24sIGggKiBibG9ja3NpemUsIHcgKiBibG9ja3NpemUsIGMgLyBibG9ja3NpemUgKiogMl1cbiAgICAgICAgOiBbbiwgYyAvIGJsb2Nrc2l6ZSAqKiAyLCBoICogYmxvY2tzaXplLCB3ICogYmxvY2tzaXplXTtcbiAgICAgIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gICAgICBjb25zdCBzaGFwZUJlZm9yZVBlcm0gPSByZXNoYXBlZElucHV0VGVuc29yLmRpbXM7XG4gICAgICBjb25zdCBzaGFwZUFmdGVyUGVybSA9IFNoYXBlVXRpbC5zb3J0QmFzZWRPblBlcm0oc2hhcGVCZWZvcmVQZXJtLCBwZXJtKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgICAgICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoc2hhcGVCZWZvcmVQZXJtLCBzaGFwZUFmdGVyUGVybSksXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGRlcHRoVG9TcGFjZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogRGVwdGhUb1NwYWNlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVEZXB0aFRvU3BhY2VQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgYXR0cmlidXRlcykpO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlRGVwdGhUb1NwYWNlQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IERlcHRoVG9TcGFjZUF0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtcbiAgICBibG9ja3NpemU6IGF0dHJpYnV0ZXMuYmxvY2tzaXplIGFzIG51bWJlcixcbiAgICBtb2RlOiBhdHRyaWJ1dGVzLm1vZGUgYXMgc3RyaW5nLFxuICAgIGZvcm1hdDogYXR0cmlidXRlcy5mb3JtYXQgYXMgJ05IV0MnIHwgJ05DSFcnLFxuICB9KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcywgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciB9IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBFaW5zdW1BdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgZXF1YXRpb246IHN0cmluZztcbn1cbi8vIFRoZSBlcXVhdGlvbiBhdHRyaWJ1dGUgdmFsdWUgaXMgYSBzdHJpbmcgd2hpY2ggY29uc2lzdHMgb2YgbGVmdCBoYW5kIHNpZGUgKExIUykgYW5kIG9wdGlvbmFsbHkgcmlnaHQgaGFuZCBzaWRlIChSSFMpXG4vLyBzZXBhcmF0ZWQgYnkgJy0+Jy4gRXguIFwiaWosamsgLT4gaWtcIiBleHByZXNzZXMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG4vLyAgICAgXCJpai0+amlcIiBleHByZXNzZXMgbWF0cml4IHRyYW5zcG9zZVxuLy8gICAgICBcImlpLT5pXCIgZGlhZ29uYWwgZWxlbWVudHMgb2YgYSBzcXVhcmUgbWF0cml4XG4vLyBMSFMgY29uc2lzdHMgb2YgYSBzZXF1ZW5jZSBvZiB0ZXJtcyBzZXBhcmF0ZWQgYnkgY29tbWFzLiBFYWNoIHRlcm0gY29ycmVzcG9uZHMgdG8gYW4gaW5wdXQgdmFyaWFibGUuXG4vLyBFYWNoIHN5bWJvbCBjb3JyZXNwb25kcyB0byBhIGRpbWVuc2lvbiBpbiB0aGUgaW5wdXQgdmFyaWFibGUuIFRoZSBzeW1ib2wgY2FuIGJlIGVpdGhlciBhIGxldHRlciwgJ2EnIHRvICd6JyBvciAnQScgdG9cbi8vICdaJyBvciAnLi4uJyB0byByZXByZXNlbnQgYXJiaXRyYXJ5IGRpbWVuc2lvbnMuXG5cbmNvbnN0IHN5bWJvbFBhdHRlcm4gPSAnW2EtekEtWl18XFxcXC5cXFxcLlxcXFwuJzsgLy8gVGhlIHBhdHRlcm4gZWFjaCBzeW1ib2wgaW4gZWFjaCB0ZXJtIGluIHRoZSBzeW1ib2xpYyBlcXVhdGlvbiBzaG91bGQgbWF0Y2hcbmNvbnN0IHRlcm1QYXR0ZXJuID0gJygnICsgc3ltYm9sUGF0dGVybiArICcpKyc7IC8vIFRoZSBwYXR0ZXJuIGVhY2ggdGVybSBpbiB0aGUgc3ltYm9saWMgZXF1YXRpb24gc2hvdWxkIG1hdGNoXG5jb25zdCB0ZXJtUGF0dGVybk9ubHkgPSAnXicgKyB0ZXJtUGF0dGVybiArICckJzsgLy8gVGhlIHBhdHRlcm5zIG9ubHkgbWF0Y2hzIGEgdGVybSBiZWdpbiB0byBlbmQuXG5jb25zdCBsaHNQYXR0ZXJuID0gJygnICsgdGVybVBhdHRlcm4gKyAnLCkqJyArIHRlcm1QYXR0ZXJuOyAvLyBUaGUgcGF0dGVybiB0aGUgTEhTIHNob3VsZCBtYXRjaFxuY29uc3QgbGhzUGF0dGVybk9ubHkgPSAnXicgKyBsaHNQYXR0ZXJuICsgJyQnOyAvLyBUaGUgcGF0dGVybnMgb25seSBtYXRjaHMgYSBMSFMgYmVnaW4gdG8gZW5kLlxuXG5pbnRlcmZhY2UgU3ltYm9sSW5mbyB7XG4gIGNvdW50OiBudW1iZXI7IC8vIFN5bWJvbCBjb3JyZXNwb25kaW5nIHRvIGEgZGltbWVuc2lvbiBvZiBhbiBpbnB1dFxuICBpbnB1dEluZGljZXM6IG51bWJlcltdOyAvLyBOdW1iZXIgb2YgaW5wdXQgdmFyaWFibGVzIHRoZSBzeW1ib2wgY29ycmVzcG9uZHMgdG9cbiAgZGltVmFsdWU6IG51bWJlcjsgLy8gTnVtYmVyIG9mIGRpbWVuc2lvbnMgdGhlIHN5bWJvbCBjb3JyZXNwb25kcyB0b1xufVxuXG5jbGFzcyBFaW5zdW1UZXJtIHtcbiAgY29uc3RydWN0b3IoaW5wdXRJbmRleCA9IC0xKSB7XG4gICAgdGhpcy5zeW1ib2xUb0luZGljZXMgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyW10+KCk7XG4gICAgdGhpcy5pbnB1dEluZGV4ID0gaW5wdXRJbmRleDtcbiAgfVxuXG4gIC8vIEFkZCBhIHN5bWJvbCB0byB0aGUgdGVybVxuICBhZGRTeW1ib2woc3ltYm9sOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpIHtcbiAgICBsZXQgdmFsdWUgPSB0aGlzLnN5bWJvbFRvSW5kaWNlcy5nZXQoc3ltYm9sKTtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdmFsdWUgPSBbaW5kZXhdO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx1ZS5wdXNoKGluZGV4KTtcbiAgICB9XG4gICAgdGhpcy5zeW1ib2xUb0luZGljZXMuc2V0KHN5bWJvbCwgdmFsdWUpO1xuICB9XG5cbiAgc3ltYm9sVG9JbmRpY2VzOiBNYXA8c3RyaW5nLCBudW1iZXJbXT47IC8vIE1hcCBmcm9tIHN5bWJvbCB0byBkaW1lbnNpb25zIG9mIHRoZSBpbnB1dCBjb3JyZXNwb25kaW5nIHRvIHRoZSB0ZXJtXG4gIGlucHV0SW5kZXg6IG51bWJlcjsgLy8gLTEgZm9yIG91dHB1dCBhbmQgMCwgMSwgMiwgLi4uIGZvciBpbnB1dHNcbn1cblxuY2xhc3MgRWluc3VtRXF1YXRpb24ge1xuICBjb25zdHJ1Y3RvcihcbiAgICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgICBwdWJsaWMgcmVhZG9ubHkgZXF1YXRpb246IHN0cmluZyxcbiAgKSB7XG4gICAgdGhpcy5oYXNFbGxpcHNpcyA9IGZhbHNlO1xuICAgIHRoaXMuc3ltYm9sVG9JbmZvID0gbmV3IE1hcDxzdHJpbmcsIFN5bWJvbEluZm8+KCk7XG4gICAgdGhpcy5saHMgPSBuZXcgQXJyYXk8RWluc3VtVGVybT4oKTtcbiAgICB0aGlzLm91dHB1dERpbXMgPSBbXTtcbiAgICAvLyBBcyByaHMgbmVlZHMgdG8gYmUgdXBkYXRlZCBhbGxvdyB1c2luZyBsZXQgaW5zdGVhZCBvZiBjb25zdCBmb3IgYm90aCBsaHMgYW5kIHJocy5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgbGV0IFtsaHMsIHJoc10gPSBlcXVhdGlvbi5pbmNsdWRlcygnLT4nKSA/IGVxdWF0aW9uLnNwbGl0KCctPicsIDIpIDogW2VxdWF0aW9uLCAnJ107XG4gICAgaWYgKCFsaHMubWF0Y2goUmVnRXhwKGxoc1BhdHRlcm5Pbmx5KSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBMSFMgdGVybScpO1xuICAgIH1cbiAgICBjb25zdCBpbnB1dFRlcm1zID0gbGhzLnNwbGl0KCcsJyk7XG4gICAgaW5wdXRUZXJtcy5mb3JFYWNoKChpbnB1dFRlcm0sIGluZGV4KSA9PiB7XG4gICAgICBjb25zdCBkaW1zID0gaW5wdXRzW2luZGV4XS5kaW1zLnNsaWNlKCk7XG4gICAgICBpZiAoIWlucHV0VGVybS5tYXRjaChSZWdFeHAodGVybVBhdHRlcm5Pbmx5KSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIExIUyB0ZXJtJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBlaW5zdW1UZXJtID0gdGhpcy5wcm9jZXNzVGVybShpbnB1dFRlcm0sIHRydWUsIGRpbXMsIGluZGV4KTtcbiAgICAgIHRoaXMubGhzLnB1c2goZWluc3VtVGVybSk7XG4gICAgfSk7XG5cbiAgICAvLyBJbml0aWFsaXplIHRoZSBSSFMgaWYgbm90IHNwZWNpZmllZFxuICAgIGlmIChyaHMgPT09ICcnKSB7XG4gICAgICAvLyBDb25zdHJ1Y3QgUkhTIGZyb20gTEhTIHRlcm1zL3N5bWJvbHNcbiAgICAgIHJocyArPSBbLi4udGhpcy5zeW1ib2xUb0luZm8uZW50cmllcygpXVxuICAgICAgICAuZmlsdGVyKChbc3ltLCBpbmZvXSkgPT4gaW5mby5jb3VudCA9PT0gMSB8fCBzeW0gPT09ICcuLi4nKVxuICAgICAgICAubWFwKChbc3ltXSkgPT4gc3ltKVxuICAgICAgICAuam9pbignJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghcmhzLm1hdGNoKFJlZ0V4cCh0ZXJtUGF0dGVybikpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBSSFMnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDb21wdXRlIG91dHB1dCBkaW1zXG4gICAgY29uc3QgcmhzU3ltYm9scyA9IHJocy5tYXRjaChSZWdFeHAoc3ltYm9sUGF0dGVybiwgJ2cnKSk7XG4gICAgcmhzU3ltYm9scz8uZm9yRWFjaCgoc3ltYm9sKSA9PiB7XG4gICAgICBpZiAoc3ltYm9sID09PSAnLi4uJykge1xuICAgICAgICB0aGlzLm91dHB1dERpbXMgPSB0aGlzLm91dHB1dERpbXMuY29uY2F0KHRoaXMuZWxsaXBzaXNEaW1zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGluZm8gPSB0aGlzLnN5bWJvbFRvSW5mby5nZXQoc3ltYm9sKTtcbiAgICAgICAgaWYgKGluZm8gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBSSFMgc3ltYm9sJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vdXRwdXREaW1zLnB1c2goaW5mby5kaW1WYWx1ZSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5yaHMgPSB0aGlzLnByb2Nlc3NUZXJtKHJocywgZmFsc2UsIHRoaXMub3V0cHV0RGltcyk7XG4gIH0gLy8gRW5kIG9mIEVpbnN1bUVxYXRpb24gY29uc3RydWN0b3JcblxuICAvLyBBZGQgYSBzeW1ib2wgdG8gdGhlIGVxdWF0aW9uXG4gIGFkZFN5bWJvbChzeW1ib2w6IHN0cmluZywgZGltVmFsdWU6IG51bWJlciwgaW5wdXRJbmRleDogbnVtYmVyKSB7XG4gICAgbGV0IGluZm8gPSB0aGlzLnN5bWJvbFRvSW5mby5nZXQoc3ltYm9sKTtcbiAgICBpZiAoaW5mbyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoaW5mby5kaW1WYWx1ZSAhPT0gZGltVmFsdWUgJiYgaW5mby5jb3VudCAhPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RpbWVuc2lvbiBtaXNtYXRjaCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5mby5jb3VudCsrO1xuICAgICAgICBpbmZvLmlucHV0SW5kaWNlcy5wdXNoKGlucHV0SW5kZXgpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpbmZvID0geyBjb3VudDogMSwgZGltVmFsdWUsIGlucHV0SW5kaWNlczogW2lucHV0SW5kZXhdIH07XG4gICAgfVxuICAgIHRoaXMuc3ltYm9sVG9JbmZvLnNldChzeW1ib2wsIGluZm8pO1xuICB9XG5cbiAgLy8gUHJvY2VzcyBvbmUgaW5wdXQvb3V0cHV0IHRlcm1cbiAgcHJvY2Vzc1Rlcm0odGVybTogc3RyaW5nLCBpc0lucHV0OiBib29sZWFuLCBkaW1zOiByZWFkb25seSBudW1iZXJbXSwgaW5kZXggPSAtMSk6IEVpbnN1bVRlcm0ge1xuICAgIGNvbnN0IHJhbmsgPSBkaW1zLmxlbmd0aDtcbiAgICBsZXQgZWxsaXBzaXMgPSBmYWxzZTtcbiAgICBsZXQgZWxsaXBzaXNEaW1zID0gW107XG4gICAgbGV0IG5leHREaW0gPSAwO1xuICAgIC8vIEZvciBvdXRwdXQgZW1wdHkgc3RyaW5nIGlzIGFsbG93ZWQgYmVjYXVzZSB0aGUgb3V0cHV0IG1heSBiZSByZWR1Y2VkIHRvIGEgc2NhbGFyIHZhbHVlXG4gICAgaWYgKCF0ZXJtLm1hdGNoKFJlZ0V4cCh0ZXJtUGF0dGVybk9ubHkpKSAmJiAhaXNJbnB1dCAmJiB0ZXJtICE9PSAnJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIExIUyB0ZXJtJyk7XG4gICAgfVxuICAgIGNvbnN0IGluZGV4U3ltYm9scyA9IHRlcm0ubWF0Y2goUmVnRXhwKHN5bWJvbFBhdHRlcm4sICdnJykpO1xuICAgIGNvbnN0IGVpbnN1bVRlcm0gPSBuZXcgRWluc3VtVGVybShpbmRleCk7XG4gICAgLy8gc3ltYm9sIGNhbiBiZSBlaXRoZXIgYSBsZXR0cmUsICdhJyB0byAneicgb3IgJ0EnIHRvICdaJywgb3IgJy4uLidcbiAgICBpbmRleFN5bWJvbHM/LmZvckVhY2goKHN5bWJvbDogc3RyaW5nLCBpOiBudW1iZXIpID0+IHtcbiAgICAgIGlmIChzeW1ib2wgPT09ICcuLi4nKSB7XG4gICAgICAgIGlmIChlbGxpcHNpcykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignT25seSBvbmUgZWxsaXBzaXMgaXMgYWxsb3dlZCBwZXIgaW5wdXQgdGVybScpO1xuICAgICAgICB9XG4gICAgICAgIGVsbGlwc2lzID0gdHJ1ZTtcbiAgICAgICAgY29uc3QgZWxsaXBzaXNEaW1MZW5ndGggPSByYW5rIC0gaW5kZXhTeW1ib2xzLmxlbmd0aCArIDE7XG4gICAgICAgIGlmIChlbGxpcHNpc0RpbUxlbmd0aCA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0VsbGlwc2lzIG91dCBvZiBib3VuZHMnKTtcbiAgICAgICAgfVxuICAgICAgICBlbGxpcHNpc0RpbXMgPSBkaW1zLnNsaWNlKG5leHREaW0sIG5leHREaW0gKyBlbGxpcHNpc0RpbUxlbmd0aCk7XG4gICAgICAgIGlmICh0aGlzLmhhc0VsbGlwc2lzKSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5lbGxpcHNpc0RpbXMubGVuZ3RoICE9PSBlbGxpcHNpc0RpbXMubGVuZ3RoIHx8XG4gICAgICAgICAgICB0aGlzLmVsbGlwc2lzRGltcy50b1N0cmluZygpICE9PSBlbGxpcHNpc0RpbXMudG9TdHJpbmcoKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFbGxpcHNpcyBkaW1lbnNpb25zIG1pc21hdGNoJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGlzSW5wdXQpIHtcbiAgICAgICAgICB0aGlzLmhhc0VsbGlwc2lzID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLmVsbGlwc2lzRGltcyA9IGVsbGlwc2lzRGltcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0VsbGlwc2lzIG11c3QgYmUgc3BlY2lmaWVkIGluIHRoZSBMSFMnKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBBZGQgJzAnLCAnMScsICcyJywgJzMnLCAnNCcsIGV0YyB0byByZXByZXNlbnQgZWxsaXBzaXMgZGltZW5zaW9ucyB0byBhdm9pZCBzcGVjaWFsIGhhbmRsaW5nXG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgZWxsaXBzaXNEaW1zLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgY29uc3Qgc3ltYm9sID0gU3RyaW5nLmZyb21DaGFyQ29kZSgnMCcuY2hhckNvZGVBdCgwKSArIGopO1xuICAgICAgICAgIGVpbnN1bVRlcm0uYWRkU3ltYm9sKHN5bWJvbCwgaSArIGopO1xuICAgICAgICAgIHRoaXMuYWRkU3ltYm9sKHN5bWJvbCwgZGltc1tuZXh0RGltKytdLCBpbmRleCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVpbnN1bVRlcm0uYWRkU3ltYm9sKHN5bWJvbCwgaSArICh0aGlzLmhhc0VsbGlwc2lzID8gdGhpcy5lbGxpcHNpc0RpbXMubGVuZ3RoIC0gMSA6IDApKTtcbiAgICAgICAgdGhpcy5hZGRTeW1ib2woc3ltYm9sLCBkaW1zW25leHREaW0rK10sIGluZGV4KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gZWluc3VtVGVybTtcbiAgfVxuXG4gIHN5bWJvbFRvSW5mbzogTWFwPHN0cmluZywgU3ltYm9sSW5mbz47IC8vIEFsbCBzeW1ib2xzIGluIHRoZSBlcXVhdGlvblxuICBoYXNFbGxpcHNpczogYm9vbGVhbjsgLy8gVGhlIGVxdWF0aW9uIGhhcyBlbGxpcHNpcyBvciBub3RcbiAgZWxsaXBzaXNEaW1zOiBudW1iZXJbXTsgLy8gVGhlIGRpbWVuc2lvbnMgb2YgdGhlIGVxdWF0aW9uIGVsbGlwc2lzIGNvcnJlc3BvbmRzIHRvLlxuICBsaHM6IEVpbnN1bVRlcm1bXTsgLy8gVGVybXMgb24gdGhlIGxlZnQtaGFuZCBzaWRlIG9mIHRoZSBlcXVhdGlvblxuICByaHM6IEVpbnN1bVRlcm07IC8vIFRlcm0gb24gdGhlIHJpZ2h0LWhhbmQgc2lkZSBvZiB0aGUgZXF1YXRpb25cbiAgb3V0cHV0RGltczogbnVtYmVyW107IC8vIE91dHB1dCBkaW1lbnNpb25zIG9mIHRoZSBlcXVhdGlvblxufSAvLyBFbmQgb2YgY2xhc3MgRWluc3VtRXF1YXRpb25cblxuY29uc3QgYXBwZW5kTWF4ID0gKG5hbWU6IHN0cmluZyk6IHN0cmluZyA9PiBuYW1lICsgJ19tYXgnO1xuXG5jb25zdCBjcmVhdGVFaW5zdW1Qcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRTaGFwZXM6IEFycmF5PHJlYWRvbmx5IG51bWJlcltdPixcbiAgZGF0YVR5cGU6IG51bWJlcixcbiAgZWluc3VtRXF1YXRpb246IEVpbnN1bUVxdWF0aW9uLFxuICBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IHJhbmtzID0gaW5wdXRTaGFwZXMubWFwKChkaW1zKSA9PiBkaW1zLmxlbmd0aCk7XG4gIGNvbnN0IGlucHV0VmFycyA9IHJhbmtzLm1hcCgocmFuaywgaW5kZXgpID0+IGlucHV0VmFyaWFibGUoYGlucHV0JHtpbmRleH1gLCBkYXRhVHlwZSwgcmFuaykpO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCk7XG4gIGNvbnN0IHVuaWZvcm1zU3ltYm9scyA9IFsuLi5laW5zdW1FcXVhdGlvbi5zeW1ib2xUb0luZm8ua2V5cygpXS5maWx0ZXIoXG4gICAgKHN5bWJvbCkgPT4gIWVpbnN1bUVxdWF0aW9uLnJocy5zeW1ib2xUb0luZGljZXMuaGFzKHN5bWJvbCksXG4gICk7XG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGlkeENvcHk6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3QgaW5pdFByb2QgPSAndmFyIHByb2QgPSAxLjA7JztcbiAgICBjb25zdCBpbml0U3VtID0gJ3ZhciBzdW0gPSAwLjA7JztcbiAgICBjb25zdCB1cGRhdGVTdW0gPSAnc3VtICs9IHByb2Q7JztcbiAgICBjb25zdCByZWR1Y2VPcHNTZXRJbmRpY2VzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGNvbnN0IHJlZHVjZU9wc0xvb3BIZWFkZXJzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGNvbnN0IHJlZHVjZU9wc0xvb3BGb290ZXJzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGNvbnN0IHJlZHVjZU9wQ29tcHV0ZTogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCBpc1JlZHVjZU9wc1dpdGhvdXRMb29wID0gZWluc3VtRXF1YXRpb24uc3ltYm9sVG9JbmZvLnNpemUgPT09IGVpbnN1bUVxdWF0aW9uLnJocy5zeW1ib2xUb0luZGljZXMuc2l6ZTtcbiAgICBlaW5zdW1FcXVhdGlvbi5zeW1ib2xUb0luZm8uZm9yRWFjaCgoaW5mbywgc3ltYm9sKSA9PiB7XG4gICAgICBpZiAoZWluc3VtRXF1YXRpb24ucmhzLnN5bWJvbFRvSW5kaWNlcy5oYXMoc3ltYm9sKSkge1xuICAgICAgICBjb25zdCBvdXRwdXRJbmRleCA9IGVpbnN1bUVxdWF0aW9uLnJocy5zeW1ib2xUb0luZGljZXMuZ2V0KHN5bWJvbCk/LlswXTtcbiAgICAgICAgaWYgKG91dHB1dEluZGV4ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBlaW5zdW1FcXVhdGlvbi5saHMuZm9yRWFjaCgodGVybSwgaSkgPT4ge1xuICAgICAgICAgICAgaWYgKGluZm8uaW5wdXRJbmRpY2VzLmluY2x1ZGVzKGkpKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGluZGljZXMgPSB0ZXJtLnN5bWJvbFRvSW5kaWNlcy5nZXQoc3ltYm9sKTtcbiAgICAgICAgICAgICAgaWYgKGluZGljZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzeW1ib2wgZXJyb3InKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpbmRpY2VzLmZvckVhY2goKGluZGV4KSA9PiB7XG4gICAgICAgICAgICAgICAgaWR4Q29weS5wdXNoKFxuICAgICAgICAgICAgICAgICAgYCR7aW5wdXRWYXJzW2ldLmluZGljZXNTZXQoXG4gICAgICAgICAgICAgICAgICAgIGBpbnB1dCR7aX1JbmRpY2VzYCxcbiAgICAgICAgICAgICAgICAgICAgaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIG91dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRJbmRpY2VzJywgb3V0cHV0SW5kZXgpLFxuICAgICAgICAgICAgICAgICAgKX1gLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlaW5zdW1FcXVhdGlvbi5saHMuZm9yRWFjaCgodGVybSwgaSkgPT4ge1xuICAgICAgICAgIGlmIChpbmZvLmlucHV0SW5kaWNlcy5pbmNsdWRlcyhpKSkge1xuICAgICAgICAgICAgY29uc3QgaW5kaWNlcyA9IHRlcm0uc3ltYm9sVG9JbmRpY2VzLmdldChzeW1ib2wpO1xuICAgICAgICAgICAgaWYgKGluZGljZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3ltYm9sIGVycm9yJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpbmRpY2VzLmZvckVhY2goKGluZGV4KSA9PiB7XG4gICAgICAgICAgICAgIHJlZHVjZU9wc1NldEluZGljZXMucHVzaChgJHtpbnB1dFZhcnNbaV0uaW5kaWNlc1NldChgaW5wdXQke2l9SW5kaWNlc2AsIGluZGV4LCBgJHtzeW1ib2x9YCl9YCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJlZHVjZU9wQ29tcHV0ZS5wdXNoKGBwcm9kICo9ICR7aW5wdXRWYXJzW2ldLmdldEJ5SW5kaWNlcyhgaW5wdXQke2l9SW5kaWNlc2ApfTtgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZWR1Y2VPcHNMb29wSGVhZGVycy5wdXNoKFxuICAgICAgICAgIGBmb3IodmFyICR7c3ltYm9sfTogdTMyID0gMDsgJHtzeW1ib2x9IDwgdW5pZm9ybXMuJHthcHBlbmRNYXgoc3ltYm9sKX07ICR7c3ltYm9sfSsrKSB7YCxcbiAgICAgICAgKTtcbiAgICAgICAgcmVkdWNlT3BzTG9vcEZvb3RlcnMucHVzaCgnfScpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGNvbnN0IHJlZHVjZU9wcyA9IGlzUmVkdWNlT3BzV2l0aG91dExvb3BcbiAgICAgID8gW1xuICAgICAgICAgIC4uLmlkeENvcHksXG4gICAgICAgICAgYGxldCBzdW0gPSAke2lucHV0VmFycy5tYXAoKGlucHV0VmFyLCBpKSA9PiBpbnB1dFZhci5nZXRCeUluZGljZXMoYGlucHV0JHtpfUluZGljZXNgKSkuam9pbignICogJyl9O2AsXG4gICAgICAgIF1cbiAgICAgIDogW1xuICAgICAgICAgIC4uLmlkeENvcHksXG4gICAgICAgICAgaW5pdFN1bSxcbiAgICAgICAgICAuLi5yZWR1Y2VPcHNMb29wSGVhZGVycyxcbiAgICAgICAgICAuLi5yZWR1Y2VPcHNTZXRJbmRpY2VzLFxuICAgICAgICAgIGluaXRQcm9kLFxuICAgICAgICAgIC4uLnJlZHVjZU9wQ29tcHV0ZSxcbiAgICAgICAgICB1cGRhdGVTdW0sXG4gICAgICAgICAgLi4ucmVkdWNlT3BzTG9vcEZvb3RlcnMsXG4gICAgICAgIF07XG4gICAgcmV0dXJuIGBcbiAgICAgICAgICAgICR7c2hhZGVySGVscGVyXG4gICAgICAgICAgICAgIC5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zU3ltYm9scy5tYXAoKHN5bWJvbCkgPT4gKHsgbmFtZTogYCR7YXBwZW5kTWF4KHN5bWJvbCl9YCwgdHlwZTogJ3UzMicgfSkpKVxuICAgICAgICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdvdXRwdXRTaXplJywgJ3UzMicpXG4gICAgICAgICAgICAgIC5kZWNsYXJlVmFyaWFibGVzKC4uLmlucHV0VmFycywgb3V0cHV0KX1cblxuICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRTaXplJyl9XG4gICAgICAgICAgICB2YXIgb3V0cHV0SW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcbiAgICAgICAgICAgICR7aW5wdXRWYXJzLm1hcCgoX3ZhciwgaSkgPT4gYHZhciBpbnB1dCR7aX1JbmRpY2VzOiAke2lucHV0VmFyc1tpXS50eXBlLmluZGljZXN9O2ApLmpvaW4oJ1xcbicpfVxuICAgICAgICAgICAgJHtyZWR1Y2VPcHMuam9pbignXFxuJyl9O1xuICAgICAgICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAnc3VtJyl9O1xuICAgICAgICAgIH1gO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdFaW5zdW0nLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGVpbnN1bUVxdWF0aW9uLmVxdWF0aW9uLCBpbnB1dERlcGVuZGVuY2llczogaW5wdXRTaGFwZXMubWFwKCgpID0+ICdyYW5rJykgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiB7XG4gICAgICAvLyBUaGUgc3ltYm9scyBmcm9tIHVuaWZvcm1TeW1ib2xzIGFycmF5IGFyZSBndWFyYW50ZWVkIHRvIGV4aXN0IGluIGVpbnN1bUVxdWF0aW9ucy5zeW1ib2xUb0luZm8gbWFwLiBUaGVcbiAgICAgIC8vIGZpbHRlciBpcyBhZGRlZCB0byBtYWtlIHN1cmUgdGhhdCBkaW1WYWx1ZSBpcyBuZXZlciAwLlxuICAgICAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zSW5pdDogUHJvZ3JhbVVuaWZvcm1bXSA9IHVuaWZvcm1zU3ltYm9sc1xuICAgICAgICAuZmlsdGVyKChzeW1ib2wpID0+IGVpbnN1bUVxdWF0aW9uLnN5bWJvbFRvSW5mby5oYXMoc3ltYm9sKSlcbiAgICAgICAgLm1hcCgoc3ltYm9sKSA9PiAoeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGVpbnN1bUVxdWF0aW9uLnN5bWJvbFRvSW5mby5nZXQoc3ltYm9sKT8uZGltVmFsdWUgfHwgMCB9KSk7XG4gICAgICBwcm9ncmFtVW5pZm9ybXNJbml0LnB1c2goeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSk7XG4gICAgICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBpbnB1dFNoYXBlc1xuICAgICAgICAubWFwKChkaW1zLCBfKSA9PiBbLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoZGltcyldKVxuICAgICAgICAucmVkdWNlKChhY2MsIGlucHV0UHJvZ3JhbVVuaWZvcm1zKSA9PiBhY2MuY29uY2F0KGlucHV0UHJvZ3JhbVVuaWZvcm1zKSwgcHJvZ3JhbVVuaWZvcm1zSW5pdCk7XG4gICAgICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhvdXRwdXRTaGFwZSkpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlIH1dLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICAgIH07XG4gICAgfSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgZWluc3VtID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBFaW5zdW1BdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IGVpbnN1bUVxdWF0aW9uID0gbmV3IEVpbnN1bUVxdWF0aW9uKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzLmVxdWF0aW9uKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBlaW5zdW1FcXVhdGlvbi5vdXRwdXREaW1zO1xuICBjb25zdCBpbnB1dFNoYXBlcyA9IGNvbnRleHQuaW5wdXRzLm1hcCgoaW5wdXQsIF8pID0+IGlucHV0LmRpbXMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWluc3VtUHJvZ3JhbUluZm8oaW5wdXRTaGFwZXMsIGNvbnRleHQuaW5wdXRzWzBdLmRhdGFUeXBlLCBlaW5zdW1FcXVhdGlvbiwgb3V0cHV0U2hhcGUpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUVpbnN1bUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBFaW5zdW1BdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgZXF1YXRpb24gPSAoYXR0cmlidXRlcy5lcXVhdGlvbiBhcyBzdHJpbmcpLnJlcGxhY2UoL1xccysvZywgJycpO1xuICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgZXF1YXRpb24gfSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdFeHBhbmQgcmVxdWlyZXMgMiBpbnB1dC4nKTtcbiAgfVxuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IHNoYXBlID0gQXJyYXkuZnJvbShpbnB1dHNbMV0uZ2V0QmlnSW50NjRBcnJheSgpLCBOdW1iZXIpO1xuXG4gIGxldCBzaGFwZUluZGV4ID0gc2hhcGUubGVuZ3RoIDwgaW5wdXRTaGFwZS5sZW5ndGggPyAwIDogc2hhcGUubGVuZ3RoIC0gaW5wdXRTaGFwZS5sZW5ndGg7XG4gIGxldCBpbnB1dFNoYXBlSW5kZXggPSBpbnB1dFNoYXBlLmxlbmd0aCA8IHNoYXBlLmxlbmd0aCA/IDAgOiBpbnB1dFNoYXBlLmxlbmd0aCAtIHNoYXBlLmxlbmd0aDtcbiAgZm9yICg7IHNoYXBlSW5kZXggPCBzaGFwZS5sZW5ndGggJiYgaW5wdXRTaGFwZUluZGV4IDwgaW5wdXRTaGFwZS5sZW5ndGg7ICsrc2hhcGVJbmRleCwgKytpbnB1dFNoYXBlSW5kZXgpIHtcbiAgICBpZiAoXG4gICAgICBzaGFwZVtzaGFwZUluZGV4XSAhPT0gaW5wdXRTaGFwZVtpbnB1dFNoYXBlSW5kZXhdICYmXG4gICAgICBzaGFwZVtzaGFwZUluZGV4XSAhPT0gMSAmJlxuICAgICAgaW5wdXRTaGFwZVtpbnB1dFNoYXBlSW5kZXhdICE9PSAxXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGFuZCByZXF1aXJlcyBzaGFwZSB0byBiZSBicm9hZGNhc3RhYmxlIHRvIGlucHV0Jyk7XG4gICAgfVxuICB9XG59O1xuXG5jb25zdCBnZXRBZGp1c3RlZFNoYXBlID0gKHNoYXBlMTogcmVhZG9ubHkgbnVtYmVyW10sIHNoYXBlMjogcmVhZG9ubHkgbnVtYmVyW10pOiBudW1iZXJbXSA9PiB7XG4gIGNvbnN0IGRpZmYgPSBzaGFwZTEubGVuZ3RoIC0gc2hhcGUyLmxlbmd0aDtcbiAgY29uc3Qgc2hhcGU6IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZGlmZjsgKytpKSB7XG4gICAgc2hhcGUucHVzaChzaGFwZTFbaV0pO1xuICB9XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc2hhcGUyLmxlbmd0aDsgKytpKSB7XG4gICAgc2hhcGUucHVzaChzaGFwZTJbaV0gPT09IDEgPyBzaGFwZTFbaSArIGRpZmZdIDogc2hhcGUyW2ldKTtcbiAgfVxuICByZXR1cm4gc2hhcGU7XG59O1xuXG5jb25zdCBjYWxjdWxhdGVPdXRwdXRTaGFwZSA9IChpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKTogbnVtYmVyW10gPT5cbiAgaW5wdXRTaGFwZS5sZW5ndGggPiBzaGFwZS5sZW5ndGggPyBnZXRBZGp1c3RlZFNoYXBlKGlucHV0U2hhcGUsIHNoYXBlKSA6IGdldEFkanVzdGVkU2hhcGUoc2hhcGUsIGlucHV0U2hhcGUpO1xuXG5jb25zdCBjcmVhdGVFeHBhbmRQcm9ncmFtSW5mbyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBzaGFwZSA9IEFycmF5LmZyb20oaW5wdXRzWzFdLmdldEJpZ0ludDY0QXJyYXkoKSwgTnVtYmVyKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGU6IG51bWJlcltdID0gY2FsY3VsYXRlT3V0cHV0U2hhcGUoaW5wdXRTaGFwZSwgc2hhcGUpO1xuICBjb25zdCBkYXRhVHlwZSA9IGlucHV0c1swXS5kYXRhVHlwZTtcbiAgY29uc3QgaXNCb29sT3JTY2FsYXIgPSBkYXRhVHlwZSA9PT0gRGF0YVR5cGUuYm9vbCB8fCBTaGFwZVV0aWwuc2l6ZShpbnB1dFNoYXBlKSA9PT0gMTtcbiAgY29uc3QgaUNvbXBvbmVudHMgPVxuICAgIGRhdGFUeXBlID09PSBEYXRhVHlwZS5ib29sID8gNCA6IGlucHV0U2hhcGUubGVuZ3RoID4gMCAmJiBpbnB1dFNoYXBlW2lucHV0U2hhcGUubGVuZ3RoIC0gMV0gJSA0ID09PSAwID8gNCA6IDE7XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBpc0Jvb2xPclNjYWxhclxuICAgID8gNFxuICAgIDogb3V0cHV0U2hhcGUubGVuZ3RoID4gMCAmJiBvdXRwdXRTaGFwZVtvdXRwdXRTaGFwZS5sZW5ndGggLSAxXSAlIDQgPT09IDBcbiAgICAgID8gNFxuICAgICAgOiAxO1xuICBjb25zdCBvdXRwdXRTaXplID0gTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIGNvbXBvbmVudHMpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBkYXRhVHlwZSwgaW5wdXRTaGFwZS5sZW5ndGgsIGlDb21wb25lbnRzKTtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgbGV0IGFzc2lnbm1lbnQ6IHN0cmluZztcbiAgICBpZiAoZGF0YVR5cGUgPT09IERhdGFUeXBlLmJvb2wpIHtcbiAgICAgIGNvbnN0IHNpbmdsZUFzc2lnbm1lbnQgPSAocmVzU3RyOiBzdHJpbmcsIHg6IG51bWJlciwgdHlwZUNhc3QgPSAnJykgPT4gYFxuICAgICAgICAgIGxldCBvdXRwdXRJbmRpY2VzJHt4fSA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcyhgb3V0cHV0T2Zmc2V0ICsgJHt4fXVgKX07XG4gICAgICAgICAgbGV0IG9mZnNldCR7eH0gPSAke2lucHV0LmJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0KGBvdXRwdXRJbmRpY2VzJHt4fWAsIG91dHB1dCl9O1xuICAgICAgICAgIGxldCBpbmRleCR7eH0gPSBvZmZzZXQke3h9IC8gNHU7XG4gICAgICAgICAgbGV0IGNvbXBvbmVudCR7eH0gPSBvZmZzZXQke3h9ICUgNHU7XG4gICAgICAgICAgJHtyZXNTdHJ9WyR7eH1dID0gJHt0eXBlQ2FzdH0oJHtpbnB1dC5nZXRCeU9mZnNldChgaW5kZXgke3h9YCl9W2NvbXBvbmVudCR7eH1dKTtcbiAgICAgICAgYDtcbiAgICAgIGFzc2lnbm1lbnQgPSBgXG4gICAgICAgIGxldCBvdXRwdXRPZmZzZXQgPSBnbG9iYWxfaWR4ICogJHtjb21wb25lbnRzfTtcbiAgICAgICAgdmFyIGRhdGEgPSB2ZWM0PHUzMj4oMCk7XG4gICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDAsICd1MzInKX1cbiAgICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KCdkYXRhJywgMSwgJ3UzMicpfVxuICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ2RhdGEnLCAyLCAndTMyJyl9XG4gICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDMsICd1MzInKX1cbiAgICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAnZGF0YScpfVxuICAgICAgfWA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFzc2lnbm1lbnQgPSBgXG4gICAgICAgIGxldCBvdXRwdXRJbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKGBnbG9iYWxfaWR4ICogJHtjb21wb25lbnRzfWApfTtcbiAgICAgICAgbGV0IGlucHV0T2Zmc2V0ID0gJHtpbnB1dC5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldCgnb3V0cHV0SW5kaWNlcycsIG91dHB1dCl9O1xuICAgICAgICBsZXQgZGF0YSA9ICR7b3V0cHV0LnR5cGUudmFsdWV9KCR7aW5wdXQuZ2V0QnlPZmZzZXQoYGlucHV0T2Zmc2V0IC8gJHtpQ29tcG9uZW50c31gKX0pO1xuICAgICAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICdkYXRhJyl9XG4gICAgICB9YDtcbiAgICB9XG4gICAgcmV0dXJuIGBcbiAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ3ZlY19zaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIG91dHB1dCl9XG4gICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMudmVjX3NpemUnKX1cbiAgICAke2Fzc2lnbm1lbnR9YDtcbiAgfTtcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dFNoYXBlLCBvdXRwdXRTaGFwZSksXG4gIF07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0V4cGFuZCcsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7b3V0cHV0U2hhcGUubGVuZ3RofTske2lDb21wb25lbnRzfSR7Y29tcG9uZW50c31gLCBpbnB1dERlcGVuZGVuY2llczogWydyYW5rJ10gfSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGV4cGFuZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFeHBhbmRQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cyksIHsgaW5wdXRzOiBbMF0gfSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbyB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG4gIFdPUktHUk9VUF9TSVpFLFxufSBmcm9tICcuL2NvbW1vbic7XG5pbXBvcnQgKiBhcyB1bmFyeSBmcm9tICcuL3VuYXJ5LW9wJztcblxuLy8gR0VMVSBpcyBkZWZpbmVkIGFzIFk9MC41KlgqKDErdGFuaCgwLjc5Nzg4NSpYKzAuMDM1Njc3KlgqWCpYKSksIHdoZXJlIFggbWF5IHByZS1hZGQgYSBiaWFzLlxuXG5jb25zdCBjcmVhdGVGYXN0R2VsdVByb2dyYW1JbmZvID0gKGlucHV0VGVuc29yczogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBkYXRhVHlwZSA9IGlucHV0VGVuc29yc1swXS5kYXRhVHlwZTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKGlucHV0VGVuc29yc1swXS5kaW1zKTtcbiAgY29uc3QgYmlhc0xlbmd0aCA9IFNoYXBlVXRpbC5zaXplKGlucHV0VGVuc29yc1sxXS5kaW1zKTtcbiAgLy8gY2FuIG9ubHkgdXNlIHZlYzQgd2hlbiBiaWFzIGxlbmd0aCBpcyBtdWx0aXBsZSBvZiA0XG4gIGNvbnN0IHVzZVZlYzQgPSBiaWFzTGVuZ3RoICUgNCA9PT0gMDtcbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKTogc3RyaW5nID0+IHtcbiAgICBjb25zdCB4ID0gaW5wdXRWYXJpYWJsZSgneCcsIGRhdGFUeXBlLCBbMV0sIDQpO1xuICAgIGNvbnN0IGJpYXMgPSBpbnB1dFZhcmlhYmxlKCdiaWFzJywgZGF0YVR5cGUsIFsxXSwgNCk7XG4gICAgY29uc3QgeSA9IG91dHB1dFZhcmlhYmxlKCd5JywgZGF0YVR5cGUsIFsxXSwgNCk7XG5cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfdmVjX3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnYmlhc19zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICBdO1xuXG4gICAgY29uc3Qgc2luZ2xlRWxlbWVudEJpYXMgPSAoaTogMCB8IDEgfCAyIHwgMykgPT4gYFxuICAgICAgbGV0IGJpYXMke2l9X29mZnNldDogdTMyID0gKGdsb2JhbF9pZHggKiA0ICsgJHtpfSkgJSB1bmlmb3Jtcy5iaWFzX3NpemU7XG4gICAgICBsZXQgYmlhcyR7aX0gPSAke2JpYXMuZ2V0QnlPZmZzZXQoYGJpYXMke2l9X29mZnNldCAvIDRgKX1bYmlhcyR7aX1fb2Zmc2V0ICUgNF07YDtcbiAgICBjb25zdCBiaWFzR2V0RXhwcmVzc2lvbiA9IHVzZVZlYzRcbiAgICAgID8gYFxuICAgICAgbGV0IGJpYXMgPSAke2JpYXMuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHggJSAodW5pZm9ybXMuYmlhc19zaXplIC8gNCknKX07YFxuICAgICAgOiBgJHtzaW5nbGVFbGVtZW50QmlhcygwKX0ke3NpbmdsZUVsZW1lbnRCaWFzKDEpfSR7c2luZ2xlRWxlbWVudEJpYXMoMil9JHtzaW5nbGVFbGVtZW50QmlhcygzKX1cbiAgICAgIGxldCBiaWFzID0gJHt4LnR5cGUudmFsdWV9KGJpYXMwLCBiaWFzMSwgYmlhczIsIGJpYXMzKTtgO1xuXG4gICAgcmV0dXJuIGAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKHgsIGJpYXMsIHkpfVxuXG4gICAgJHt1bmFyeS5mYXN0R2VsdUltcGwodGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZShkYXRhVHlwZSkpfVxuXG4gICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KFdPUktHUk9VUF9TSVpFKX1cbiAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF92ZWNfc2l6ZScpfVxuXG4gICAgICBsZXQgeCA9ICR7eC5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpfTtcbiAgICAgICR7Ymlhc0dldEV4cHJlc3Npb259XG4gICAgICBsZXQgeF9pbiA9IHggKyBiaWFzO1xuICAgICAgJHt5LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgdW5hcnkuZmFzdEdlbHVFeHByZXNzaW9uKCd4X2luJykpfVxuICAgIH1gO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0Zhc3RHZWx1V2l0aEJpYXMnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke3VzZVZlYzR9YCwgaW5wdXREZXBlbmRlbmNpZXM6IFsndHlwZScsICd0eXBlJ10gfSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgZ2V0UnVuRGF0YTogKGlucHV0cykgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IGlucHV0c1swXS5kaW1zLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zOiBbXG4gICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDQpIH0sXG4gICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBiaWFzTGVuZ3RoIH0sXG4gICAgICBdLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIFdPUktHUk9VUF9TSVpFIC8gNCkgfSxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBmYXN0R2VsdSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBpZiAoY29udGV4dC5pbnB1dHMubGVuZ3RoIDwgMiB8fCBTaGFwZVV0aWwuc2l6ZShjb250ZXh0LmlucHV0c1sxXS5kaW1zKSA9PT0gMCkge1xuICAgIHVuYXJ5LmZhc3RHZWx1KGNvbnRleHQpO1xuICB9IGVsc2Uge1xuICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVGYXN0R2VsdVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzKSk7XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2F0aGVyQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIGF4aXM6IG51bWJlcjtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignR2F0aGVyIHJlcXVpcmVzIDIgaW5wdXRzLicpO1xuICB9XG59O1xuXG5jb25zdCBjcmVhdGVHYXRoZXJQcm9ncmFtSW5mbyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogR2F0aGVyQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBpbmRpY2VzU2hhcGUgPSBpbnB1dHNbMV0uZGltcztcblxuICBjb25zdCBpbnB1dFJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aDtcbiAgY29uc3QgYXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF0dHJpYnV0ZXMuYXhpcywgaW5wdXRSYW5rKTtcblxuICBjb25zdCBvdXRwdXRTaGFwZSA9IGlucHV0U2hhcGUuc2xpY2UoMCk7XG4gIG91dHB1dFNoYXBlLnNwbGljZShheGlzLCAxLCAuLi5pbmRpY2VzU2hhcGUpO1xuXG4gIGNvbnN0IGF4aXNEaW1MaW1pdCA9IGlucHV0U2hhcGVbYXhpc107XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBpbnB1dHNbMF0uZGF0YVR5cGUgPT09IERhdGFUeXBlLmJvb2wgPyA0IDogMTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IE1hdGguY2VpbChTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyBjb21wb25lbnRzKTtcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBheGlzRGltTGltaXQgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYXhpcyB9LFxuICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1swXS5kaW1zLCBpbnB1dHNbMV0uZGltcywgb3V0cHV0U2hhcGUpLFxuICBdO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGRhdGEgPSBpbnB1dFZhcmlhYmxlKCdkYXRhJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcy5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IGluZGljZXMgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dEluZGljZXMnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGlucHV0c1sxXS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcblxuICAgIGNvbnN0IGNhbGNEYXRhSW5kaWNlcyA9ICh4OiBudW1iZXIgfCBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICAgICAgY29uc3QgaW5kaWNlc1JhbmsgPSBpbmRpY2VzU2hhcGUubGVuZ3RoO1xuICAgICAgbGV0IGNhbGNTdHIgPSBgdmFyIGluZGljZXNJbmRpY2VzJHt4fSAgPSAke2luZGljZXMudHlwZS5pbmRpY2VzfSgwKTtgO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbmRpY2VzUmFuazsgaSsrKSB7XG4gICAgICAgIGNhbGNTdHIgKz0gYCR7aW5kaWNlc1JhbmsgPiAxID8gYGluZGljZXNJbmRpY2VzJHt4fVske2l9XWAgOiBgaW5kaWNlc0luZGljZXMke3h9YH0gPSAke1xuICAgICAgICAgIG91dHB1dFNoYXBlLmxlbmd0aCA+IDEgPyBgb3V0cHV0SW5kaWNlcyR7eH1bdW5pZm9ybXMuYXhpcyArICR7aX1dYCA6IGBvdXRwdXRJbmRpY2VzJHt4fWBcbiAgICAgICAgfTtgO1xuICAgICAgfVxuICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgdmFyIGlkeCR7eH0gPSAke2luZGljZXMuZ2V0QnlJbmRpY2VzKGBpbmRpY2VzSW5kaWNlcyR7eH1gKX07XG4gICAgICAgICAgaWYgKGlkeCR7eH0gPCAwKSB7XG4gICAgICAgICAgICBpZHgke3h9ID0gaWR4JHt4fSArIHVuaWZvcm1zLmF4aXNEaW1MaW1pdDtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIGRhdGFJbmRpY2VzJHt4fSA6ICR7ZGF0YS50eXBlLmluZGljZXN9O1xuICAgICAgICBgO1xuICAgICAgZm9yIChsZXQgaSA9IDAsIGogPSAwOyBpIDwgaW5wdXRSYW5rOyBpKyspIHtcbiAgICAgICAgaWYgKGkgPT09IGF4aXMpIHtcbiAgICAgICAgICBjYWxjU3RyICs9IGAke2lucHV0UmFuayA+IDEgPyBgZGF0YUluZGljZXMke3h9WyR7aX1dYCA6IGBkYXRhSW5kaWNlcyR7eH1gfSA9IHUzMihpZHgke3h9KTtgO1xuICAgICAgICAgIGogKz0gaW5kaWNlc1Jhbms7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2FsY1N0ciArPSBgJHtpbnB1dFJhbmsgPiAxID8gYGRhdGFJbmRpY2VzJHt4fVske2l9XWAgOiBgZGF0YUluZGljZXMke3h9YH0gPSAke1xuICAgICAgICAgICAgb3V0cHV0U2hhcGUubGVuZ3RoID4gMSA/IGBvdXRwdXRJbmRpY2VzJHt4fVske2p9XWAgOiBgb3V0cHV0SW5kaWNlcyR7eH1gXG4gICAgICAgICAgfTtgO1xuICAgICAgICAgIGorKztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGNhbGNTdHI7XG4gICAgfTtcbiAgICBsZXQgYXNzaWdubWVudDogc3RyaW5nO1xuICAgIGlmIChpbnB1dHNbMF0uZGF0YVR5cGUgPT09IERhdGFUeXBlLmJvb2wpIHtcbiAgICAgIGNvbnN0IHNpbmdsZUFzc2lnbm1lbnQgPSAocmVzU3RyOiBzdHJpbmcsIHg6IG51bWJlciwgdHlwZUNhc3QgPSAnJykgPT4gYFxuICAgICAgICAgIGxldCBvdXRwdXRJbmRpY2VzJHt4fSA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcyhgb3V0cHV0T2Zmc2V0ICsgJHt4fXVgKX07XG4gICAgICAgICAgJHtjYWxjRGF0YUluZGljZXMoeCl9O1xuICAgICAgICAgIGxldCBvZmZzZXQke3h9ID0gJHtkYXRhLmluZGljZXNUb09mZnNldChgZGF0YUluZGljZXMke3h9YCl9O1xuICAgICAgICAgIGxldCBpbmRleCR7eH0gPSBvZmZzZXQke3h9IC8gNHU7XG4gICAgICAgICAgbGV0IGNvbXBvbmVudCR7eH0gPSBvZmZzZXQke3h9ICUgNHU7XG4gICAgICAgICAgJHtyZXNTdHJ9WyR7eH1dID0gJHt0eXBlQ2FzdH0oJHtkYXRhLmdldEJ5T2Zmc2V0KGBpbmRleCR7eH1gKX1bY29tcG9uZW50JHt4fV0pO1xuICAgICAgICBgO1xuICAgICAgYXNzaWdubWVudCA9IGBcbiAgICAgICAgbGV0IG91dHB1dE9mZnNldCA9IGdsb2JhbF9pZHggKiAke2NvbXBvbmVudHN9O1xuICAgICAgICB2YXIgdmFsdWUgPSB2ZWM0PHUzMj4oMCk7XG4gICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgndmFsdWUnLCAwLCAndTMyJyl9XG4gICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgndmFsdWUnLCAxLCAndTMyJyl9XG4gICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgndmFsdWUnLCAyLCAndTMyJyl9XG4gICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgndmFsdWUnLCAzLCAndTMyJyl9XG4gICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3ZhbHVlJyl9XG4gICAgICBgO1xuICAgIH0gZWxzZSB7XG4gICAgICBhc3NpZ25tZW50ID0gYFxuICAgICAgbGV0IG91dHB1dEluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgICAke2NhbGNEYXRhSW5kaWNlcygnJyl9O1xuICAgICAgbGV0IHZhbHVlID0gJHtkYXRhLmdldEJ5SW5kaWNlcygnZGF0YUluZGljZXMnKX07XG4gICAgICAke291dHB1dC5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICd2YWx1ZScpfTtcbiAgICAgIGA7XG4gICAgfVxuICAgIHJldHVybiBgXG4gICAgICAke3NoYWRlckhlbHBlclxuICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdvdXRwdXRTaXplJywgJ3UzMicpXG4gICAgICAgIC5yZWdpc3RlclVuaWZvcm0oJ2F4aXNEaW1MaW1pdCcsICdpMzInKVxuICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdheGlzJywgJ3UzMicpXG4gICAgICAgIC5kZWNsYXJlVmFyaWFibGVzKGRhdGEsIGluZGljZXMsIG91dHB1dCl9XG4gICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0U2l6ZScpfVxuICAgICAgICAke2Fzc2lnbm1lbnR9XG4gICAgICB9YDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnR2F0aGVyJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5LCBpbnB1dERlcGVuZGVuY2llczogWydyYW5rJywgJ3JhbmsnXSB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VHYXRoZXJBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogR2F0aGVyQXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyBheGlzOiBhdHRyaWJ1dGVzLmF4aXMgYXMgbnVtYmVyIH0pO1xuXG5leHBvcnQgY29uc3QgZ2F0aGVyID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBHYXRoZXJBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IGlucHV0cyA9IGNvbnRleHQuaW5wdXRzO1xuICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlR2F0aGVyUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIsIFVuaWZvcm1zQXJyYXlUeXBlIH0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdhdGhlck5EQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGJhdGNoRGltczogbnVtYmVyO1xufVxuXG5jb25zdCBjb21wdXRlU2xpY2VPZmZzZXRzID0gKFxuICBjb250ZXh0OiBDb21wdXRlQ29udGV4dCxcbiAgaW5kaWNlc0RhdGE6IFRlbnNvclZpZXcsXG4gIHNpemVzRnJvbVNsaWNlRGltc0RhdGE6IG51bWJlcltdLFxuICBiYXRjaERpbXM6IG51bWJlcixcbiAgaW5wdXREaW1zOiByZWFkb25seSBudW1iZXJbXSxcbiAgbnVtU2xpY2VzOiBudW1iZXIsXG4gIG51bVNsaWNlc1BlckJhdGNoOiBudW1iZXIsXG4gIGlucHV0QmF0Y2hTdHJpZGU6IG51bWJlcixcbiAgbnVtU2xpY2VEaW1zOiBudW1iZXIsXG4pID0+IHtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBudW1TbGljZXMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYmF0Y2hEaW1zIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGlucHV0RGltcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBzaXplc0Zyb21TbGljZURpbXNEYXRhIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG51bVNsaWNlc1BlckJhdGNoIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGlucHV0QmF0Y2hTdHJpZGUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogbnVtU2xpY2VEaW1zIH0sXG4gIF07XG5cbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBbbnVtU2xpY2VzXTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5kaWNlc0RhdGEuZGltcywgb3V0cHV0U2hhcGUpKTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBpbmRpY2VzID0gaW5wdXRWYXJpYWJsZSgnaW5kaWNlc19kYXRhJywgaW5kaWNlc0RhdGEuZGF0YVR5cGUsIGluZGljZXNEYXRhLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnaW5wdXRfc2xpY2Vfb2Zmc2V0c19kYXRhJywgRGF0YVR5cGUudWludDMyLCAxLCAxKTtcbiAgICBjb25zdCB2YXJpYWJsZXMgPSBbaW5kaWNlcywgb3V0cHV0XTtcbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdiYXRjaF9kaW1zJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2lucHV0X2RpbXMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBpbnB1dERpbXMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdzaXplc19mcm9tX3NsaWNlX2RpbXNfZGF0YScsIHR5cGU6ICd1MzInLCBsZW5ndGg6IHNpemVzRnJvbVNsaWNlRGltc0RhdGEubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdudW1fc2xpY2VzX3Blcl9iYXRjaCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdpbnB1dF9iYXRjaF9zdHJpZGUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnbnVtX3NsaWNlX2RpbXMnLCB0eXBlOiAndTMyJyB9LFxuICAgIF07XG4gICAgcmV0dXJuIGBcbiAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi52YXJpYWJsZXMpfVxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuICAgIGxldCBiYXRjaF9pZHggPSBnbG9iYWxfaWR4IC8gdW5pZm9ybXMubnVtX3NsaWNlc19wZXJfYmF0Y2g7XG4gICAgbGV0IGJhc2Vfb2Zmc2V0ID0gYmF0Y2hfaWR4ICogdW5pZm9ybXMuaW5wdXRfYmF0Y2hfc3RyaWRlO1xuXG4gICAgbGV0IHNsaWNlX2luZGljZXNfYmFzZV9vZmZzZXQgPSBnbG9iYWxfaWR4ICogdW5pZm9ybXMubnVtX3NsaWNlX2RpbXM7XG4gICAgdmFyIHJlbGF0aXZlX3NsaWNlX29mZnNldCA9IDA7XG4gICAgZm9yICh2YXIgZGltX2lkeCA9IDB1OyBkaW1faWR4IDwgdW5pZm9ybXMubnVtX3NsaWNlX2RpbXM7IGRpbV9pZHggKyspIHtcbiAgICAgIHZhciBpbmRleCA9IGkzMihpbmRpY2VzX2RhdGFbZGltX2lkeCArIHNsaWNlX2luZGljZXNfYmFzZV9vZmZzZXRdLngpO1xuICAgICAgbGV0IGlucHV0X2RpbV9pZHggPSB1bmlmb3Jtcy5iYXRjaF9kaW1zICsgZGltX2lkeDtcbiAgICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgICAgJHtcbiAgICAgICAgICBpbnB1dERpbXMubGVuZ3RoID09PSAxXG4gICAgICAgICAgICA/ICdpbmRleCArPSBpMzIodW5pZm9ybXMuaW5wdXRfZGltcyk7J1xuICAgICAgICAgICAgOiAnaW5kZXggKz0gaTMyKHVuaWZvcm1zLmlucHV0X2RpbXNbaW5wdXRfZGltX2lkeF0pOydcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgJHtcbiAgICAgICAgc2l6ZXNGcm9tU2xpY2VEaW1zRGF0YS5sZW5ndGggPT09IDFcbiAgICAgICAgICA/ICdyZWxhdGl2ZV9zbGljZV9vZmZzZXQgKz0gaW5kZXggKiBpMzIodW5pZm9ybXMuc2l6ZXNfZnJvbV9zbGljZV9kaW1zX2RhdGEpOydcbiAgICAgICAgICA6ICdyZWxhdGl2ZV9zbGljZV9vZmZzZXQgKz0gaW5kZXggKiBpMzIodW5pZm9ybXMuc2l6ZXNfZnJvbV9zbGljZV9kaW1zX2RhdGFbZGltX2lkeF0pOydcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpbnB1dF9zbGljZV9vZmZzZXRzX2RhdGFbZ2xvYmFsX2lkeF0gPSAgYmFzZV9vZmZzZXQgKyB1MzIocmVsYXRpdmVfc2xpY2Vfb2Zmc2V0KTtcbiAgfWA7XG4gIH07XG5cbiAgcmV0dXJuIGNvbnRleHQuY29tcHV0ZShcbiAgICB7XG4gICAgICBuYW1lOiAnY29tcHV0ZVNsaWNlT2Zmc2V0cycsXG4gICAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtpbnB1dERpbXMubGVuZ3RofV8ke3NpemVzRnJvbVNsaWNlRGltc0RhdGEubGVuZ3RofWAsIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnXSB9LFxuICAgICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBjb250ZXh0LmlucHV0c1sxXS5kYXRhVHlwZSB9XSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwobnVtU2xpY2VzIC8gNjQpIH0sXG4gICAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICAgIH0pLFxuICAgICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIH0sXG4gICAgeyBpbnB1dHM6IFtpbmRpY2VzRGF0YV0sIG91dHB1dHM6IFstMV0gfSxcbiAgKVswXTtcbn07XG5cbmV4cG9ydCBjb25zdCBnYXRoZXJORCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogR2F0aGVyTkRBdHRyaWJ1dGVzKSA9PiB7XG4gIGNvbnN0IGlucHV0cyA9IGNvbnRleHQuaW5wdXRzO1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGlucHV0VHlwZSA9IGlucHV0c1swXS5kYXRhVHlwZTtcbiAgY29uc3QgaW5kaWNlc1NoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG4gIGNvbnN0IG51bVNsaWNlRGltcyA9IGluZGljZXNTaGFwZVtpbmRpY2VzU2hhcGUubGVuZ3RoIC0gMV07XG4gIGNvbnN0IG51bVNsaWNlcyA9IFNoYXBlVXRpbC5zaXplVG9EaW1lbnNpb24oaW5kaWNlc1NoYXBlLCBpbmRpY2VzU2hhcGUubGVuZ3RoIC0gMSk7XG4gIGNvbnN0IHNsaWNlU2l6ZSA9IFNoYXBlVXRpbC5zaXplRnJvbURpbWVuc2lvbihpbnB1dFNoYXBlLCBhdHRyaWJ1dGVzLmJhdGNoRGltcyArIG51bVNsaWNlRGltcyk7XG4gIGNvbnN0IG51bUJhdGNoZXMgPSBTaGFwZVV0aWwuc2l6ZVRvRGltZW5zaW9uKGlucHV0U2hhcGUsIGF0dHJpYnV0ZXMuYmF0Y2hEaW1zKTtcbiAgY29uc3QgaW5wdXRCYXRjaFN0cmlkZSA9IFNoYXBlVXRpbC5zaXplRnJvbURpbWVuc2lvbihpbnB1dFNoYXBlLCBhdHRyaWJ1dGVzLmJhdGNoRGltcyk7XG4gIGNvbnN0IG51bVNsaWNlc1BlckJhdGNoID0gbnVtU2xpY2VzIC8gbnVtQmF0Y2hlcztcbiAgY29uc3Qgc2l6ZXNGcm9tU2xpY2VEaW1zID0gbmV3IEFycmF5KG51bVNsaWNlRGltcyk7XG4gIGxldCBydW5uaW5nUHJvZHVjdCA9IHNsaWNlU2l6ZTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1TbGljZURpbXM7ICsraSkge1xuICAgIHNpemVzRnJvbVNsaWNlRGltc1tudW1TbGljZURpbXMgLSAxIC0gaV0gPSBydW5uaW5nUHJvZHVjdDtcbiAgICBydW5uaW5nUHJvZHVjdCAqPSBpbnB1dFNoYXBlW2F0dHJpYnV0ZXMuYmF0Y2hEaW1zICsgbnVtU2xpY2VEaW1zIC0gMSAtIGldO1xuICB9XG5cbiAgY29uc3QgaW5wdXRTbGljZU9mZnNldHMgPSBjb21wdXRlU2xpY2VPZmZzZXRzKFxuICAgIGNvbnRleHQsXG4gICAgaW5wdXRzWzFdLFxuICAgIHNpemVzRnJvbVNsaWNlRGltcyxcbiAgICBhdHRyaWJ1dGVzLmJhdGNoRGltcyxcbiAgICBpbnB1dFNoYXBlLFxuICAgIG51bVNsaWNlcyxcbiAgICBudW1TbGljZXNQZXJCYXRjaCxcbiAgICBpbnB1dEJhdGNoU3RyaWRlLFxuICAgIG51bVNsaWNlRGltcyxcbiAgKTtcblxuICBjb25zdCBsYXN0SW5kaWNlc0RpbWVuc2lvbiA9IGF0dHJpYnV0ZXMuYmF0Y2hEaW1zICsgbnVtU2xpY2VEaW1zO1xuICBpZiAobGFzdEluZGljZXNEaW1lbnNpb24gPiBpbnB1dFNoYXBlLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignbGFzdCBkaW1lbnNpb24gb2YgaW5kaWNlcyBtdXN0IG5vdCBiZSBsYXJnZXIgdGhhbiByYW5rIG9mIGlucHV0IHRlbnNvcicpO1xuICB9XG5cbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbmRpY2VzU2hhcGUuc2xpY2UoMCwgLTEpLmNvbmNhdChpbnB1dFNoYXBlLnNsaWNlKGxhc3RJbmRpY2VzRGltZW5zaW9uKSk7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHNsaWNlU2l6ZSB9LFxuICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1swXS5kaW1zLCBpbnB1dFNsaWNlT2Zmc2V0cy5kaW1zLCBvdXRwdXRTaGFwZSksXG4gIF07XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdkYXRhJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcy5sZW5ndGgpO1xuICAgIGNvbnN0IGluZGljZXMgPSBpbnB1dFZhcmlhYmxlKCdzbGljZV9vZmZzZXRzJywgRGF0YVR5cGUudWludDMyLCBpbnB1dFNsaWNlT2Zmc2V0cy5kaW1zLmxlbmd0aCk7XG5cbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuICAgIHJldHVybiBgXG4gICAgICAgICAgJHtzaGFkZXJIZWxwZXJcbiAgICAgICAgICAgIC5yZWdpc3RlclVuaWZvcm0oJ291dHB1dF9zaXplJywgJ3UzMicpXG4gICAgICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdzbGljZV9zaXplJywgJ3UzMicpXG4gICAgICAgICAgICAuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgaW5kaWNlcywgb3V0cHV0KX1cbiAgICAgICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cbiAgICAgICAgICBsZXQgc2xpY2Vfb2Zmc2V0ID0gc2xpY2Vfb2Zmc2V0c1tnbG9iYWxfaWR4IC8gdW5pZm9ybXMuc2xpY2Vfc2l6ZV07XG4gICAgICAgICAgb3V0cHV0W2dsb2JhbF9pZHhdID0gZGF0YVt1MzIoc2xpY2Vfb2Zmc2V0KSArIGdsb2JhbF9pZHggJSB1bmlmb3Jtcy5zbGljZV9zaXplXTtcbiAgICAgICAgfWA7XG4gIH07XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICB7XG4gICAgICBuYW1lOiAnR2F0aGVyTkQnLFxuICAgICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYXR0cmlidXRlcy5jYWNoZUtleSwgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuaycsICdyYW5rJ10gfSxcbiAgICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRUeXBlIH1dLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICAgIH0pLFxuICAgICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIH0sXG4gICAgeyBpbnB1dHM6IFtpbnB1dHNbMF0sIGlucHV0U2xpY2VPZmZzZXRzXSB9LFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlR2F0aGVyTkRBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogR2F0aGVyTkRBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgYmF0Y2hEaW1zID0gYXR0cmlidXRlcy5iYXRjaF9kaW1zIGFzIG51bWJlcjtcbiAgcmV0dXJuIHtcbiAgICBiYXRjaERpbXMsXG4gICAgY2FjaGVLZXk6ICcnLFxuICB9O1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgdGVuc29yVHlwZVRvV3NnbFZhbHVlVHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBHYXRoZXJCbG9ja1F1YW50aXplZEF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICBnYXRoZXJBeGlzOiBudW1iZXI7XG4gIHF1YW50aXplQXhpczogbnVtYmVyO1xuICBibG9ja1NpemU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBHYXRoZXJCbG9ja1F1YW50aXplZEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKGlucHV0cy5sZW5ndGggPCAzIHx8IGlucHV0cy5sZW5ndGggPiA0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdHYXRoZXJCbG9ja1F1YW50aXplZCByZXF1aXJlcyAzIG9yIDQgaW5wdXRzLicpO1xuICB9XG4gIGNvbnN0IHF1YW50aXplQXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF0dHJpYnV0ZXMucXVhbnRpemVBeGlzLCBpbnB1dHNbMF0uZGltcy5sZW5ndGgpO1xuICBjb25zdCBibG9ja1NpemUgPSBhdHRyaWJ1dGVzLmJsb2NrU2l6ZTtcbiAgY29uc3QgZGF0YSA9IGlucHV0c1swXTtcbiAgY29uc3Qgc2NhbGVzID0gaW5wdXRzWzJdO1xuICBjb25zdCB6ZXJvUG9pbnQgPSBpbnB1dHMubGVuZ3RoID09PSA0ID8gaW5wdXRzWzNdIDogdW5kZWZpbmVkO1xuICBpZiAoXG4gICAgc2NhbGVzLmRpbXMubGVuZ3RoICE9PSBkYXRhLmRpbXMubGVuZ3RoIHx8XG4gICAgIWRhdGEuZGltc1xuICAgICAgLm1hcCgoZCwgaSkgPT4gKGkgPT09IHF1YW50aXplQXhpcyA/IE1hdGguY2VpbChkIC8gYmxvY2tTaXplKSA9PT0gc2NhbGVzLmRpbXNbaV0gOiBkID09PSBzY2FsZXMuZGltc1tpXSkpXG4gICAgICAucmVkdWNlKChhLCBiKSA9PiBhICYmIGIsIHRydWUpXG4gICkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICdTY2FsZXMgbXVzdCBoYXZlIHRoZSBzYW1lIHJhbmsgYXMgdGhlIGlucHV0IHRlbnNvciBhbmQgdGhlIGRpbXMgc2hvdWxkIG1hdGNoIGV4Y2VwdCBvbiBnYXRoZXJBeGlzLicsXG4gICAgKTtcbiAgfVxuICAvLyBUT0RPIFVuY29tbWVudCB0aGUgZm9sbG93aW5nIGNoZWNrIG9uY2UgdGhlIHRlc3QgY2FzZSBjcmVhdGlvbiBjb2RlIGlzIGZpeGVkIHRvIGNyZWF0ZSBkYXRhIGNvcnJlY3RseSBhbGlnbmVkLlxuICAvLyBjb25zdCBpbmRpY2VzID0gaW5wdXRzWzFdO1xuICAvLyBjb25zdCB2YWxpZEluZGV4ID0gKGluZGV4OiBudW1iZXIpID0+IGluZGV4ID49IDAgJiYgaW5kZXggPCBkYXRhLmRpbXNbYXR0cmlidXRlcy5nYXRoZXJBeGlzXTtcbiAgLy8gaWYgKGluZGljZXMuZGF0YVR5cGUgPT09IERhdGFUeXBlLmludDMyICYmIGluZGljZXMuZ2V0SW50MzJBcnJheSgpLnNvbWUoKHYpID0+ICF2YWxpZEluZGV4KHYpKSB8fFxuICAvLyAgICAgaW5kaWNlcy5kYXRhVHlwZSA9PT0gRGF0YVR5cGUuaW50NjQgJiYgaW5kaWNlcy5nZXRCaWdJbnQ2NEFycmF5KCkuc29tZSgodikgPT4gIXZhbGlkSW5kZXgoTnVtYmVyKHYpKSkpIHtcbiAgLy8gICB0aHJvdyBuZXcgRXJyb3IoJ0luZGljZXMgbXVzdCBiZSB3aXRoaW4gdGhlIGJvdW5kcyBvZiB0aGUgZ2F0aGVyQXhpcy4nKTtcbiAgLy8gfVxuICBpZiAoemVyb1BvaW50KSB7XG4gICAgaWYgKHplcm9Qb2ludC5kYXRhVHlwZSAhPT0gZGF0YS5kYXRhVHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdaZXJvIHBvaW50IG11c3QgaGF2ZSB0aGUgc2FtZSBkYXRhIHR5cGUgYXMgdGhlIGlucHV0IHRlbnNvci4nKTtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgemVyb1BvaW50LmRpbXMubGVuZ3RoICE9PSBzY2FsZXMuZGltcy5sZW5ndGggfHxcbiAgICAgICF6ZXJvUG9pbnQuZGltcy5tYXAoKGQsIGkpID0+IGQgPT09IHNjYWxlcy5kaW1zW2ldKS5yZWR1Y2UoKGEsIGIpID0+IGEgJiYgYiwgdHJ1ZSlcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ1plcm8gcG9pbnQgbXVzdCBoYXZlIHRoZSBzYW1lIHJhbmsgYXMgdGhlIGlucHV0IHRlbnNvciBhbmQgdGhlIGRpbXMgc2hvdWxkIG1hdGNoIGV4Y2VwdCBvbiBxdWFudGl6ZUF4aXMuJyxcbiAgICAgICk7XG4gICAgfVxuICB9XG59O1xuXG5jb25zdCBjcmVhdGVHYXRoZXJCbG9ja1F1YW50aXplZFByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogR2F0aGVyQmxvY2tRdWFudGl6ZWRBdHRyaWJ1dGVzLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGluZGljZXNTaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuICBjb25zdCBpbnB1dFJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aDtcbiAgY29uc3QgZ2F0aGVyQXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF0dHJpYnV0ZXMuZ2F0aGVyQXhpcywgaW5wdXRSYW5rKTtcbiAgY29uc3QgcXVhbnRpemVBeGlzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4aXMoYXR0cmlidXRlcy5xdWFudGl6ZUF4aXMsIGlucHV0UmFuayk7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gaW5wdXRTaGFwZS5zbGljZSgwKTtcbiAgb3V0cHV0U2hhcGUuc3BsaWNlKGdhdGhlckF4aXMsIDEsIC4uLmluZGljZXNTaGFwZSk7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gIGNvbnN0IG91dHB1dFR5cGUgPSBpbnB1dHNbMl0uZGF0YVR5cGU7XG4gIGNvbnN0IGlucHV0VHlwZSA9IGlucHV0c1swXS5kYXRhVHlwZTtcbiAgY29uc3QgaXNTaWduZWQgPSBpbnB1dFR5cGUgPT09IERhdGFUeXBlLmludDQ7IC8vIGlucHV0IGRhdGEgdHlwZSBpcyBlaXRoZXIgaW50NCBvciB1aW50NC5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHF1YW50aXplQXhpcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBnYXRoZXJBeGlzIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGF0dHJpYnV0ZXMuYmxvY2tTaXplIH0sXG4gICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoLi4uaW5wdXRzLm1hcCgoaW5wdXQsIF8pID0+IGlucHV0LmRpbXMpLCBvdXRwdXRTaGFwZSksXG4gIF07XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgZGF0YSA9IGlucHV0VmFyaWFibGUoJ2RhdGEnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgaW5kaWNlcyA9IGlucHV0VmFyaWFibGUoJ2lucHV0SW5kaWNlcycsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBzY2FsZXMgPSBpbnB1dFZhcmlhYmxlKCdzY2FsZXMnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgemVyb1BvaW50ID1cbiAgICAgIGlucHV0cy5sZW5ndGggPiAzID8gaW5wdXRWYXJpYWJsZSgnemVyb1BvaW50JywgaW5wdXRzWzNdLmRhdGFUeXBlLCBpbnB1dHNbM10uZGltcy5sZW5ndGgpIDogdW5kZWZpbmVkO1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBvdXRwdXRUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuICAgIGNvbnN0IGlucHV0VmFyaWFibGVzID0gW2RhdGEsIGluZGljZXMsIHNjYWxlc107XG4gICAgaWYgKHplcm9Qb2ludCkge1xuICAgICAgaW5wdXRWYXJpYWJsZXMucHVzaCh6ZXJvUG9pbnQpO1xuICAgIH1cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdxdWFudGl6ZV9heGlzJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2dhdGhlcl9heGlzJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2Jsb2NrX3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgIF07XG4gICAgcmV0dXJuIGBcbiAgICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcmlhYmxlcywgb3V0cHV0KX1cbiAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgIGxldCBvdXRwdXRfaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcbiAgICAgICAgdmFyIGluZGljZXNfaW5kaWNlcyA9ICR7aW5kaWNlcy50eXBlLmluZGljZXN9KDApO1xuICAgICAgICAkeygoKSA9PiB7XG4gICAgICAgICAgaWYgKGluZGljZXNTaGFwZS5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICByZXR1cm4gYFxuICAgICAgICAgIGZvciAodmFyIGk6IHUzMiA9IDA7IGkgPCAke2luZGljZXNTaGFwZS5sZW5ndGh9OyBpKyspIHtcbiAgICAgICAgICAgIGxldCBpbmRleCA9ICR7b3V0cHV0LmluZGljZXNHZXQoJ291dHB1dF9pbmRpY2VzJywgJ3VuaWZvcm1zLmdhdGhlcl9heGlzICsgaScpfTtcbiAgICAgICAgICAgICR7aW5kaWNlcy5pbmRpY2VzU2V0KCdpbmRpY2VzX2luZGljZXMnLCAnaScsICdpbmRleCcpfTtcbiAgICAgICAgICB9YDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGBpbmRpY2VzX2luZGljZXMgPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRfaW5kaWNlcycsICd1bmlmb3Jtcy5nYXRoZXJfYXhpcycpfTtgO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkoKX07XG4gICAgICAgIHZhciBkYXRhX2luZGljZXMgPSAke2RhdGEudHlwZS5pbmRpY2VzfSgwKTtcbiAgICAgICAgZm9yICh2YXIgaTogdTMyID0gMDsgaSA8IHVuaWZvcm1zLmdhdGhlcl9heGlzOyBpKyspIHtcbiAgICAgICAgICBsZXQgaW5kZXggPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRfaW5kaWNlcycsICdpJyl9O1xuICAgICAgICAgICR7ZGF0YS5pbmRpY2VzU2V0KCdkYXRhX2luZGljZXMnLCAnaScsICdpbmRleCcpfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaW5kZXhfZnJvbV9pbmRpY2VzID0gJHtpbmRpY2VzLmdldEJ5SW5kaWNlcygnaW5kaWNlc19pbmRpY2VzJyl9O1xuICAgICAgICBpZiAoaW5kZXhfZnJvbV9pbmRpY2VzIDwgMCkge1xuICAgICAgICAgIGluZGV4X2Zyb21faW5kaWNlcyArPSAke2lucHV0U2hhcGVbZ2F0aGVyQXhpc119O1xuICAgICAgICB9XG4gICAgICAgICR7ZGF0YS5pbmRpY2VzU2V0KCdkYXRhX2luZGljZXMnLCAndW5pZm9ybXMuZ2F0aGVyX2F4aXMnLCAndTMyKGluZGV4X2Zyb21faW5kaWNlcyknKX07XG4gICAgICAgIGZvciAodmFyIGkgPSB1bmlmb3Jtcy5nYXRoZXJfYXhpcyArIDE7IGkgPCAke291dHB1dFNoYXBlLmxlbmd0aH07IGkrKykge1xuICAgICAgICAgIGxldCBpbmRleCA9ICR7b3V0cHV0LmluZGljZXNHZXQoJ291dHB1dF9pbmRpY2VzJywgYGkgKyAke2luZGljZXNTaGFwZS5sZW5ndGh9IC0gMWApfTtcbiAgICAgICAgICAke2RhdGEuaW5kaWNlc1NldCgnZGF0YV9pbmRpY2VzJywgJ2knLCAnaW5kZXgnKX07XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGRhdGFfb2Zmc2V0ID0gJHtkYXRhLmluZGljZXNUb09mZnNldCgnZGF0YV9pbmRpY2VzJyl9O1xuICAgICAgICBsZXQgZGF0YV9pbmRleCA9IGRhdGFfb2Zmc2V0ICUgODtcbiAgICAgICAgLy8gQ29udmVydCA0LWJpdCBwYWNrZWQgZGF0YSB0byA4LWJpdCBwYWNrZWQgZGF0YS5cbiAgICAgICAgbGV0IHBhY2tlZF80Yml0X3F1YW50aXplZF9kYXRhID0gJHtkYXRhLmdldEJ5T2Zmc2V0KCdkYXRhX29mZnNldCAvIDgnKX07XG4gICAgICAgIGxldCBwYWNrZWRfOGJpdF9xdWFudGl6ZWRfZGF0YSA9IChwYWNrZWRfNGJpdF9xdWFudGl6ZWRfZGF0YSA+PiAoNCAqIChkYXRhX2luZGV4ICUgMikpKSAmIDB4MGYwZjBmMGY7XG4gICAgICAgIGxldCBxdWFudGl6ZWRfZGF0YV92ZWMgPSAke2lzU2lnbmVkID8gJ3VucGFjazR4STgnIDogJ3VucGFjazR4VTgnfSh1MzIocGFja2VkXzhiaXRfcXVhbnRpemVkX2RhdGEpKTtcbiAgICAgICAgbGV0IHF1YW50aXplZF9kYXRhID0gcXVhbnRpemVkX2RhdGFfdmVjW2RhdGFfaW5kZXggLyAyXTtcbiAgICAgICAgdmFyIHNjYWxlX2luZGljZXMgPSBkYXRhX2luZGljZXM7XG4gICAgICAgIGxldCBxdWFudGl6ZV9heGlzX2luZGV4ID0gJHtzY2FsZXMuaW5kaWNlc0dldCgnZGF0YV9pbmRpY2VzJywgJ3VuaWZvcm1zLnF1YW50aXplX2F4aXMnKX0gLyB1bmlmb3Jtcy5ibG9ja19zaXplO1xuICAgICAgICAke3NjYWxlcy5pbmRpY2VzU2V0KCdzY2FsZV9pbmRpY2VzJywgJ3VuaWZvcm1zLnF1YW50aXplX2F4aXMnLCAncXVhbnRpemVfYXhpc19pbmRleCcpfTtcbiAgICAgICAgdmFyIHNjYWxlID0gJHtzY2FsZXMuZ2V0QnlJbmRpY2VzKCdzY2FsZV9pbmRpY2VzJyl9O1xuICAgICAgICAkeygoKSA9PiB7XG4gICAgICAgICAgaWYgKCF6ZXJvUG9pbnQpIHtcbiAgICAgICAgICAgIHJldHVybiAndmFyIHplcm9fcG9pbnQgPSAwJztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfaW5kaWNlcyA9IHNjYWxlX2luZGljZXM7XG4gICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X29mZnNldCA9ICR7emVyb1BvaW50LmluZGljZXNUb09mZnNldCgnemVyb19wb2ludF9pbmRpY2VzJyl9O1xuICAgICAgICAgICAgICBsZXQgemVyb19wb2ludF9pbmRleCA9IHplcm9fcG9pbnRfb2Zmc2V0ICUgODtcbiAgICAgICAgICAgICAgbGV0IHBhY2tlZF80Yml0X3plcm9fcG9pbnRzID0gJHt6ZXJvUG9pbnQuZ2V0QnlPZmZzZXQoJ3plcm9fcG9pbnRfb2Zmc2V0IC8gOCcpfTtcbiAgICAgICAgICAgICAgbGV0IHBhY2tlZF84Yml0X3plcm9fcG9pbnRzID0gKHBhY2tlZF80Yml0X3plcm9fcG9pbnRzID4+ICg0ICogKHplcm9fcG9pbnRfaW5kZXggJSAyKSkpICYgMHgwZjBmMGYwZjtcbiAgICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfdmVjID0gJHtpc1NpZ25lZCA/ICd1bnBhY2s0eEk4JyA6ICd1bnBhY2s0eFU4J30odTMyKHBhY2tlZF84Yml0X3plcm9fcG9pbnRzKSk7XG4gICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50ID0gemVyb19wb2ludF92ZWNbemVyb19wb2ludF9pbmRleCAvIDJdO2A7XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpfTtcbiAgICAgICAgbGV0IGRlcXVhbnRpemVkX2RhdGEgPSAke3RlbnNvclR5cGVUb1dzZ2xWYWx1ZVR5cGUob3V0cHV0VHlwZSl9KHF1YW50aXplZF9kYXRhIC0gemVyb19wb2ludCkgKiBzY2FsZTtcbiAgICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAnZGVxdWFudGl6ZWRfZGF0YScpfTtcbiAgICB9YDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnR2F0aGVyQmxvY2tRdWFudGl6ZWQnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBgJHthdHRyaWJ1dGVzLmNhY2hlS2V5fTske2lucHV0c1xuICAgICAgICAuZmlsdGVyKChfLCBpKSA9PiBpICE9PSAxKVxuICAgICAgICAubWFwKChpbnB1dCkgPT4gaW5wdXQuZGltcy5qb2luKCdfJykpXG4gICAgICAgIC5qb2luKCc7Jyl9YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzOiBBcnJheS5mcm9tKHsgbGVuZ3RoOiBpbnB1dHMubGVuZ3RoIH0sIChfdiwgX2kpID0+ICdyYW5rJyksXG4gICAgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBvdXRwdXRUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBnYXRoZXJCbG9ja1F1YW50aXplZCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogR2F0aGVyQmxvY2tRdWFudGl6ZWRBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IGlucHV0cyA9IGNvbnRleHQuaW5wdXRzO1xuICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlR2F0aGVyQmxvY2tRdWFudGl6ZWRQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcykpO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlR2F0aGVyQmxvY2tRdWFudGl6ZWRBdHRyaWJ1dGVzID0gKFxuICBhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbik6IEdhdGhlckJsb2NrUXVhbnRpemVkQXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe1xuICAgIGJsb2NrU2l6ZTogYXR0cmlidXRlcy5ibG9ja1NpemUgYXMgbnVtYmVyLFxuICAgIGdhdGhlckF4aXM6IGF0dHJpYnV0ZXMuZ2F0aGVyQXhpcyBhcyBudW1iZXIsXG4gICAgcXVhbnRpemVBeGlzOiBhdHRyaWJ1dGVzLnF1YW50aXplQXhpcyBhcyBudW1iZXIsXG4gIH0pO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IEF0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcywgaW5wdXRWYXJpYWJsZSwgb3V0cHV0VmFyaWFibGUsIFNoYWRlckhlbHBlciB9IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBHYXRoZXJFbGVtZW50c0F0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICBheGlzOiBudW1iZXI7XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0dhdGhlckVsZW1lbnRzIHJlcXVpcmVzIDIgaW5wdXRzLicpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCA8IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0dhdGhlckVsZW1lbnRzIHJlcXVpcmVzIHRoYXQgdGhlIGRhdGEgaW5wdXQgYmUgcmFuayA+PSAxLicpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gaW5wdXRzWzFdLmRpbXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBHYXRoZXJFbGVtZW50cyByZXF1aXJlcyB0aGF0IHRoZSBkYXRhIGlucHV0IGFuZFxuICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcyBpbnB1dCB0ZW5zb3JzIGJlIG9mIHNhbWUgcmFuay5gKTtcbiAgfVxufTtcblxuY29uc3QgY3JlYXRlR2F0aGVyRWxlbWVudHNQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IEdhdGhlckVsZW1lbnRzQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBpbnB1dE91dHB1dERhdGFUeXBlID0gaW5wdXRzWzBdLmRhdGFUeXBlO1xuICBjb25zdCBpbnB1dFJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aDtcblxuICBjb25zdCBpbmRpY2VzU2hhcGUgPSBpbnB1dHNbMV0uZGltcztcbiAgY29uc3QgaW5kaWNlc0RhdGFUeXBlID0gaW5wdXRzWzFdLmRhdGFUeXBlO1xuICBjb25zdCBheGlzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4aXMoYXR0cmlidXRlcy5heGlzLCBpbnB1dFJhbmspO1xuICBjb25zdCBheGlzRGltTGltaXQgPSBpbnB1dFNoYXBlW2F4aXNdO1xuXG4gIGNvbnN0IG91dHB1dFNoYXBlID0gaW5kaWNlc1NoYXBlLnNsaWNlKDApO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuXG4gIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBpbnB1dE91dHB1dERhdGFUeXBlLCBpbnB1dFJhbmspO1xuICBjb25zdCBpbmRpY2VzID0gaW5wdXRWYXJpYWJsZSgnaW5kaWNlc0lucHV0JywgaW5kaWNlc0RhdGFUeXBlLCBpbmRpY2VzU2hhcGUubGVuZ3RoKTtcbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0T3V0cHV0RGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCk7XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogYXhpc0RpbUxpbWl0IH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGF4aXMgfSxcbiAgXTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRTaGFwZSwgaW5kaWNlc1NoYXBlLCBvdXRwdXRTaGFwZSkpO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsncmFuaycsICdyYW5rJ107XG5cbiAgLy8gaW50NjQgaW5kaWNlcyB3b3VsZCBiZSB0cmVhdGVkIGFzIGxpdHRsZSBlbmRpYW4gaTMyIHdpdGggYXNzdW1wdGlvbiB0aGV5IGZhbGwgaW4gaTMyIGxpbWl0c1xuICAvLyBUaGF0IGFzc3VtcHRpb24gaXMgc2FmZSBhcyBpdCdzIG5vdCBwb3NzaWJsZSB0byBhbGxvY2F0ZSA+MmdiIGJ1ZmZlciBmb3IgaW5wdXQgdGVuc29yXG4gIC8vIElucHV0IGRhdGEgd2lsbCBiZSB0cmVhdGVkIGFzIHUzMiBvciB0d28gdTMyIGZvciA4LWJ5dGUgdGVuc29yc1xuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcbiAgICAgICR7c2hhZGVySGVscGVyXG4gICAgICAgIC5yZWdpc3RlclVuaWZvcm0oJ291dHB1dFNpemUnLCAndTMyJylcbiAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnYXhpc0RpbUxpbWl0JywgJ2kzMicpXG4gICAgICAgIC5yZWdpc3RlclVuaWZvcm0oJ2F4aXMnLCAndTMyJylcbiAgICAgICAgLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIGluZGljZXMsIG91dHB1dCl9XG4gICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dFNpemUnKX1cblxuICAgICAgbGV0IG91dHB1dEluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG5cbiAgICAgIHZhciBpZHggPSAke2luZGljZXMuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKX07XG4gICAgICBpZiAoaWR4IDwgMCkge1xuICAgICAgICBpZHggPSBpZHggKyB1bmlmb3Jtcy5heGlzRGltTGltaXQ7XG4gICAgICB9XG4gICAgICB2YXIgaW5wdXRJbmRpY2VzID0gJHtpbnB1dC50eXBlLmluZGljZXN9KG91dHB1dEluZGljZXMpO1xuICAgICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dEluZGljZXMnLCAndW5pZm9ybXMuYXhpcycsICd1MzIoaWR4KScpfTtcbiAgICAgIGxldCB2YWx1ZSA9ICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dEluZGljZXMnKX07XG5cbiAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3ZhbHVlJyl9O1xuICB9YDtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdHYXRoZXJFbGVtZW50cycsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaW5wdXREZXBlbmRlbmNpZXMgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlR2F0aGVyRWxlbWVudHNBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogR2F0aGVyRWxlbWVudHNBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IGF4aXM6IGF0dHJpYnV0ZXMuYXhpcyBhcyBudW1iZXIgfSk7XG5cbmV4cG9ydCBjb25zdCBnYXRoZXJFbGVtZW50cyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogR2F0aGVyRWxlbWVudHNBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IGlucHV0cyA9IGNvbnRleHQuaW5wdXRzO1xuICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlR2F0aGVyRWxlbWVudHNQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcykpO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgR2VtbVV0aWwsIFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGlzIG1pc3NpbmcnKTtcbiAgfVxuICBpZiAoaW5wdXRzLmxlbmd0aCA8IDIgfHwgaW5wdXRzLmxlbmd0aCA+IDMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFpZCBpbnB1dCBudW1iZXIuJyk7XG4gIH1cblxuICAvLyAnQycgY2FuIGJlIG9mIGRpbWVuc2lvbmFsaXR5IDAsIDEgb3IgMiBvbmx5XG4gIGlmIChpbnB1dHMubGVuZ3RoID09PSAzICYmIGlucHV0c1syXS5kaW1zLmxlbmd0aCA+IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaW5wdXQgc2hhcGUgb2YgQycpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS5kYXRhVHlwZSAhPT0gaW5wdXRzWzFdLmRhdGFUeXBlIHx8IChpbnB1dHMubGVuZ3RoID09PSAzICYmIGlucHV0c1swXS5kYXRhVHlwZSAhPT0gaW5wdXRzWzJdLmRhdGFUeXBlKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgdHlwZXMgYXJlIG1pc21hdGNoZWQnKTtcbiAgfVxufTtcblxuZXhwb3J0IGludGVyZmFjZSBHZW1tQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHRyYW5zQTogYm9vbGVhbjtcbiAgdHJhbnNCOiBib29sZWFuO1xuICBhbHBoYTogbnVtYmVyO1xuICBiZXRhOiBudW1iZXI7XG59XG5cbmNvbnN0IGNyZWF0ZUdlbW1Qcm9ncmFtSW5mbyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogR2VtbUF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGFTaGFwZSA9IGlucHV0c1swXS5kaW1zLnNsaWNlKCk7XG4gIGNvbnN0IGJTaGFwZSA9IGlucHV0c1sxXS5kaW1zLnNsaWNlKCk7XG4gIGNvbnN0IFtNLCBOLCBLXSA9IEdlbW1VdGlsLmdldFNoYXBlT2ZHZW1tUmVzdWx0KFxuICAgIGFTaGFwZSxcbiAgICBhdHRyaWJ1dGVzLnRyYW5zQSxcbiAgICBiU2hhcGUsXG4gICAgYXR0cmlidXRlcy50cmFuc0IsXG4gICAgaW5wdXRzLmxlbmd0aCA9PT0gMyA/IGlucHV0c1syXS5kaW1zIDogdW5kZWZpbmVkLFxuICApO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IFtNLCBOXTtcbiAgaWYgKCFvdXRwdXRTaGFwZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNhbid0IHVzZSBnZW1tIG9uIHRoZSBnaXZlbiB0ZW5zb3JzXCIpO1xuICB9XG4gIGNvbnN0IHRpbGVTaXplID0gMTY7XG4gIGNvbnN0IG51bVRpbGVOID0gTWF0aC5jZWlsKE4gLyB0aWxlU2l6ZSk7XG4gIGNvbnN0IG51bVRpbGVNID0gTWF0aC5jZWlsKE0gLyB0aWxlU2l6ZSk7XG4gIC8vIFRPRE86IEZpbmQgdGhlIGNvbmRpdGlvbiB3aGVuIHRvIHVzZSB0aGUgbmFpdmUgb25lLlxuICBjb25zdCB1c2VTaGFyZWQgPSB0cnVlO1xuXG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogdXNlU2hhcmVkID8gbnVtVGlsZU4gOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IE0gfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogTiB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBLIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogYXR0cmlidXRlcy5hbHBoYSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IGF0dHJpYnV0ZXMuYmV0YSB9LFxuICBdO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsndHlwZScsICd0eXBlJ107XG4gIGlmIChpbnB1dHMubGVuZ3RoID09PSAzKSB7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzJdLmRpbXMpKTtcbiAgICBpbnB1dERlcGVuZGVuY2llcy5wdXNoKCdyYW5rJyk7XG4gIH1cbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0cHV0U2hhcGUpKTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBsZXQgbGluZSA9ICcnO1xuICAgIGlmIChhdHRyaWJ1dGVzLnRyYW5zQSAmJiBhdHRyaWJ1dGVzLnRyYW5zQikge1xuICAgICAgbGluZSA9ICd2YWx1ZSArPSBhW2sgKiB1bmlmb3Jtcy5NICsgbV0gKiBiW24gKiB1bmlmb3Jtcy5LICsga107JztcbiAgICB9IGVsc2UgaWYgKGF0dHJpYnV0ZXMudHJhbnNBICYmICFhdHRyaWJ1dGVzLnRyYW5zQikge1xuICAgICAgbGluZSA9ICd2YWx1ZSArPSBhW2sgKiB1bmlmb3Jtcy5NICsgbV0gKiBiW2sgKiB1bmlmb3Jtcy5OICsgbl07JztcbiAgICB9IGVsc2UgaWYgKCFhdHRyaWJ1dGVzLnRyYW5zQSAmJiBhdHRyaWJ1dGVzLnRyYW5zQikge1xuICAgICAgbGluZSA9ICd2YWx1ZSArPSBhW20gKiB1bmlmb3Jtcy5LICsga10gKiBiW24gKiB1bmlmb3Jtcy5LICsga107JztcbiAgICB9IGVsc2UgaWYgKCFhdHRyaWJ1dGVzLnRyYW5zQSAmJiAhYXR0cmlidXRlcy50cmFuc0IpIHtcbiAgICAgIGxpbmUgPSAndmFsdWUgKz0gYVttICogdW5pZm9ybXMuSyArIGtdICogYltrICogdW5pZm9ybXMuTiArIG5dOyc7XG4gICAgfVxuXG4gICAgY29uc3QgY2FsY3VsYXRlQWxwaGEgPSBhdHRyaWJ1dGVzLmFscGhhID09PSAxID8gJycgOiAndmFsdWUgKj0gdW5pZm9ybXMuYWxwaGE7JztcbiAgICBjb25zdCBhID0gaW5wdXRWYXJpYWJsZSgnYScsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMpO1xuICAgIGNvbnN0IGIgPSBpbnB1dFZhcmlhYmxlKCdiJywgaW5wdXRzWzFdLmRhdGFUeXBlLCBpbnB1dHNbMV0uZGltcyk7XG4gICAgY29uc3QgZGF0YVR5cGUgPSBhLnR5cGUudmFsdWU7XG4gICAgbGV0IGM6IEluZGljZXNIZWxwZXIgfCBudWxsID0gbnVsbDtcbiAgICBjb25zdCB2YXJpYWJsZXMgPSBbYSwgYl07XG4gICAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMpIHtcbiAgICAgIGMgPSBpbnB1dFZhcmlhYmxlKCdjJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBpbnB1dHNbMl0uZGltcy5sZW5ndGgpO1xuICAgICAgdmFyaWFibGVzLnB1c2goYyk7XG4gICAgfVxuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCk7XG4gICAgdmFyaWFibGVzLnB1c2gob3V0cHV0KTtcbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdNJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ04nLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnSycsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdhbHBoYScsIHR5cGU6ICdmMzInIH0sXG4gICAgICB7IG5hbWU6ICdiZXRhJywgdHlwZTogJ2YzMicgfSxcbiAgICBdO1xuICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4udmFyaWFibGVzKX1cblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuXG4gICAgbGV0IG0gPSBnbG9iYWxfaWR4IC8gdW5pZm9ybXMuTjtcbiAgICBsZXQgbiA9IGdsb2JhbF9pZHggJSB1bmlmb3Jtcy5OO1xuXG4gICAgdmFyIHZhbHVlID0gJHtkYXRhVHlwZX0oMCk7XG4gICAgZm9yICh2YXIgazogdTMyID0gMHU7IGsgPCB1bmlmb3Jtcy5LOyBrKyspIHtcbiAgICAgICR7bGluZX1cbiAgICB9XG5cbiAgICAke2NhbGN1bGF0ZUFscGhhfVxuICAgICR7KCgpID0+IHtcbiAgICAgIGlmIChjICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGBsZXQgY09mZnNldCA9ICR7Yy5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldCgndmVjMihtLCBuKScsIG91dHB1dCl9OyB2YWx1ZSArPSAke1xuICAgICAgICAgIGRhdGFUeXBlXG4gICAgICAgIH0odW5pZm9ybXMuYmV0YSkgKiAke2MuZ2V0QnlPZmZzZXQoJ2NPZmZzZXQnKX07YDtcbiAgICAgIH1cbiAgICAgIHJldHVybiAnJztcbiAgICB9KSgpfVxuICAgIG91dHB1dFtnbG9iYWxfaWR4XSA9IHZhbHVlO1xuICB9YDtcbiAgfTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2VTaGFyZWQgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBhID0gaW5wdXRWYXJpYWJsZSgnYScsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMpO1xuICAgIGNvbnN0IGIgPSBpbnB1dFZhcmlhYmxlKCdiJywgaW5wdXRzWzFdLmRhdGFUeXBlLCBpbnB1dHNbMV0uZGltcyk7XG4gICAgbGV0IGM6IEluZGljZXNIZWxwZXIgfCBudWxsID0gbnVsbDtcbiAgICBjb25zdCB2YXJpYWJsZXMgPSBbYSwgYl07XG4gICAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMpIHtcbiAgICAgIGMgPSBpbnB1dFZhcmlhYmxlKCdjJywgaW5wdXRzWzJdLmRhdGFUeXBlLCBpbnB1dHNbMl0uZGltcy5sZW5ndGgpO1xuICAgICAgdmFyaWFibGVzLnB1c2goYyk7XG4gICAgfVxuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCk7XG4gICAgdmFyaWFibGVzLnB1c2gob3V0cHV0KTtcbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdudW1fdGlsZV9uJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ00nLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnTicsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdLJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2FscGhhJywgdHlwZTogJ2YzMicgfSxcbiAgICAgIHsgbmFtZTogJ2JldGEnLCB0eXBlOiAnZjMyJyB9LFxuICAgIF07XG5cbiAgICBsZXQgY2FsY1Jlc3VsdCA9ICcnO1xuICAgIGxldCBmaWxsV29ya2dyb3VwTWVtb3J5ID0gJyc7XG4gICAgaWYgKGF0dHJpYnV0ZXMudHJhbnNBICYmIGF0dHJpYnV0ZXMudHJhbnNCKSB7XG4gICAgICBmaWxsV29ya2dyb3VwTWVtb3J5ID0gYFxuICAgICAgdmFyIGNvbCA9IHRpbGVfcm93X3N0YXJ0ICsgbG9jYWxfaWQueDtcbiAgICAgIHZhciByb3cgPSBrX3N0YXJ0ICsgbG9jYWxfaWQueTtcbiAgICAgIGlmIChjb2wgPCB1bmlmb3Jtcy5NICYmIHJvdyA8IHVuaWZvcm1zLkspIHtcbiAgICAgICAgdGlsZV9hW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdID0gYVtyb3cgKiB1bmlmb3Jtcy5NICsgY29sXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRpbGVfYVtsb2NhbF9pZC55XVtsb2NhbF9pZC54XSA9ICR7YS50eXBlLnZhbHVlfSgwKTtcbiAgICAgIH1cblxuICAgICAgY29sID0ga19zdGFydCArIGxvY2FsX2lkLng7XG4gICAgICByb3cgPSB0aWxlX2NvbF9zdGFydCArIGxvY2FsX2lkLnk7XG4gICAgICBpZiAoY29sIDwgdW5pZm9ybXMuSyAmJiByb3cgPCB1bmlmb3Jtcy5OKSB7XG4gICAgICAgIHRpbGVfYltsb2NhbF9pZC55XVtsb2NhbF9pZC54XSA9IGJbcm93ICogdW5pZm9ybXMuSyArIGNvbF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aWxlX2JbbG9jYWxfaWQueV1bbG9jYWxfaWQueF0gPSAke2IudHlwZS52YWx1ZX0oMCk7XG4gICAgICB9XG4gICAgICBgO1xuICAgICAgY2FsY1Jlc3VsdCA9IGB2YWx1ZSArPSB0aWxlX2Fba11bbG9jYWxfaWQueV0gKiB0aWxlX2JbbG9jYWxfaWQueF1ba107YDtcbiAgICB9IGVsc2UgaWYgKGF0dHJpYnV0ZXMudHJhbnNBICYmICFhdHRyaWJ1dGVzLnRyYW5zQikge1xuICAgICAgZmlsbFdvcmtncm91cE1lbW9yeSA9IGBcbiAgICAgIHZhciBjb2wgPSB0aWxlX3Jvd19zdGFydCArIGxvY2FsX2lkLng7XG4gICAgICB2YXIgcm93ID0ga19zdGFydCArIGxvY2FsX2lkLnk7XG4gICAgICBpZiAoY29sIDwgdW5pZm9ybXMuTSAmJiByb3cgPCB1bmlmb3Jtcy5LKSB7XG4gICAgICAgIHRpbGVfYVtsb2NhbF9pZC55XVtsb2NhbF9pZC54XSA9IGFbcm93ICogdW5pZm9ybXMuTSArIGNvbF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aWxlX2FbbG9jYWxfaWQueV1bbG9jYWxfaWQueF0gPSAke2EudHlwZS52YWx1ZX0oMCk7XG4gICAgICB9XG5cbiAgICAgIGNvbCA9IHRpbGVfY29sX3N0YXJ0ICsgbG9jYWxfaWQueDtcbiAgICAgIHJvdyA9IGtfc3RhcnQgKyBsb2NhbF9pZC55O1xuICAgICAgaWYgKGNvbCA8IHVuaWZvcm1zLk4gJiYgcm93IDwgdW5pZm9ybXMuSykge1xuICAgICAgICB0aWxlX2JbbG9jYWxfaWQueV1bbG9jYWxfaWQueF0gPSBiW3JvdyAqIHVuaWZvcm1zLk4gKyBjb2xdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGlsZV9iW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdID0gJHtiLnR5cGUudmFsdWV9KDApO1xuICAgICAgfVxuICAgICAgYDtcbiAgICAgIGNhbGNSZXN1bHQgPSBgdmFsdWUgKz0gdGlsZV9hW2tdW2xvY2FsX2lkLnldICogdGlsZV9iW2tdW2xvY2FsX2lkLnhdO2A7XG4gICAgfSBlbHNlIGlmICghYXR0cmlidXRlcy50cmFuc0EgJiYgYXR0cmlidXRlcy50cmFuc0IpIHtcbiAgICAgIGZpbGxXb3JrZ3JvdXBNZW1vcnkgPSBgXG4gICAgICB2YXIgY29sID0ga19zdGFydCArIGxvY2FsX2lkLng7XG4gICAgICB2YXIgcm93ID0gdGlsZV9yb3dfc3RhcnQgKyBsb2NhbF9pZC55O1xuICAgICAgaWYgKGNvbCA8IHVuaWZvcm1zLksgJiYgcm93IDwgdW5pZm9ybXMuTSkge1xuICAgICAgICB0aWxlX2FbbG9jYWxfaWQueV1bbG9jYWxfaWQueF0gPSBhW3JvdyAqIHVuaWZvcm1zLksgKyBjb2xdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGlsZV9hW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdID0gJHthLnR5cGUudmFsdWV9KDApO1xuICAgICAgfVxuXG4gICAgICBjb2wgPSBrX3N0YXJ0ICsgbG9jYWxfaWQueDtcbiAgICAgIHJvdyA9IHRpbGVfY29sX3N0YXJ0ICsgbG9jYWxfaWQueTtcbiAgICAgIGlmIChjb2wgPCB1bmlmb3Jtcy5LICYmIHJvdyA8IHVuaWZvcm1zLk4pIHtcbiAgICAgICAgdGlsZV9iW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdID0gYltyb3cgKiB1bmlmb3Jtcy5LICsgY29sXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRpbGVfYltsb2NhbF9pZC55XVtsb2NhbF9pZC54XSA9ICR7Yi50eXBlLnZhbHVlfSgwKTtcbiAgICAgIH1cbiAgICAgIGA7XG4gICAgICBjYWxjUmVzdWx0ID0gYHZhbHVlICs9IHRpbGVfYVtsb2NhbF9pZC55XVtrXSAqIHRpbGVfYltsb2NhbF9pZC54XVtrXTtgO1xuICAgIH0gZWxzZSBpZiAoIWF0dHJpYnV0ZXMudHJhbnNBICYmICFhdHRyaWJ1dGVzLnRyYW5zQikge1xuICAgICAgZmlsbFdvcmtncm91cE1lbW9yeSA9IGBcbiAgICAgIHZhciBjb2wgPSBrX3N0YXJ0ICsgbG9jYWxfaWQueDtcbiAgICAgIHZhciByb3cgPSB0aWxlX3Jvd19zdGFydCArIGxvY2FsX2lkLnk7XG4gICAgICBpZiAoY29sIDwgdW5pZm9ybXMuSyAmJiByb3cgPCB1bmlmb3Jtcy5NKSB7XG4gICAgICAgIHRpbGVfYVtsb2NhbF9pZC55XVtsb2NhbF9pZC54XSA9IGFbcm93ICogdW5pZm9ybXMuSyArIGNvbF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aWxlX2FbbG9jYWxfaWQueV1bbG9jYWxfaWQueF0gPSAke2EudHlwZS52YWx1ZX0oMCk7XG4gICAgICB9XG5cbiAgICAgIGNvbCA9IHRpbGVfY29sX3N0YXJ0ICsgbG9jYWxfaWQueDtcbiAgICAgIHJvdyA9IGtfc3RhcnQgKyBsb2NhbF9pZC55O1xuICAgICAgaWYgKGNvbCA8IHVuaWZvcm1zLk4gJiYgcm93IDwgdW5pZm9ybXMuSykge1xuICAgICAgICB0aWxlX2JbbG9jYWxfaWQueV1bbG9jYWxfaWQueF0gPSBiW3JvdyAqIHVuaWZvcm1zLk4gKyBjb2xdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGlsZV9iW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdID0gJHtiLnR5cGUudmFsdWV9KDApO1xuICAgICAgfVxuICAgICAgYDtcbiAgICAgIGNhbGNSZXN1bHQgPSBgdmFsdWUgKz0gdGlsZV9hW2xvY2FsX2lkLnldW2tdICogdGlsZV9iW2tdW2xvY2FsX2lkLnhdO2A7XG4gICAgfVxuXG4gICAgY29uc3QgY2FsY3VsYXRlQWxwaGEgPSBhdHRyaWJ1dGVzLmFscGhhID09PSAxID8gJycgOiAndmFsdWUgKj0gdW5pZm9ybXMuYWxwaGE7JztcblxuICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoLi4udmFyaWFibGVzKX1cbiAgdmFyPHdvcmtncm91cD4gdGlsZV9hOiBhcnJheTxhcnJheTwke2EudHlwZS5zdG9yYWdlfSwgJHt0aWxlU2l6ZX0+LCAke3RpbGVTaXplfT47XG4gIHZhcjx3b3JrZ3JvdXA+IHRpbGVfYjogYXJyYXk8YXJyYXk8JHtiLnR5cGUuc3RvcmFnZX0sICR7dGlsZVNpemV9PiwgJHt0aWxlU2l6ZX0+O1xuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoW3RpbGVTaXplLCB0aWxlU2l6ZSwgMV0pfVxuICAgIGxldCB0aWxlX2NvbF9zdGFydCA9ICh3b3JrZ3JvdXBfaW5kZXggJSB1bmlmb3Jtcy5udW1fdGlsZV9uKSAqICR7dGlsZVNpemV9O1xuICAgIGxldCB0aWxlX3Jvd19zdGFydCA9ICh3b3JrZ3JvdXBfaW5kZXggLyB1bmlmb3Jtcy5udW1fdGlsZV9uKSAqICR7dGlsZVNpemV9O1xuICAgIGxldCBudW1fdGlsZXMgPSAodW5pZm9ybXMuSyAtIDEpIC8gJHt0aWxlU2l6ZX0gKyAxO1xuICAgIHZhciBrX3N0YXJ0ID0gMHU7XG4gICAgdmFyIHZhbHVlID0gJHtvdXRwdXQudHlwZS52YWx1ZX0oMCk7XG4gICAgZm9yICh2YXIgdDogdTMyID0gMHU7IHQgPCBudW1fdGlsZXM7IHQrKykge1xuICAgICAgJHtmaWxsV29ya2dyb3VwTWVtb3J5fVxuICAgICAga19zdGFydCA9IGtfc3RhcnQgKyAke3RpbGVTaXplfTtcbiAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgZm9yICh2YXIgazogdTMyID0gMHU7IGsgPCAke3RpbGVTaXplfTsgaysrKSB7XG4gICAgICAgICR7Y2FsY1Jlc3VsdH1cbiAgICAgIH1cbiAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcbiAgICB9XG5cbiAgICAke2NhbGN1bGF0ZUFscGhhfVxuICAgIGxldCBtID0gdGlsZV9yb3dfc3RhcnQgKyBsb2NhbF9pZC55O1xuICAgIGxldCBuID0gdGlsZV9jb2xfc3RhcnQgKyBsb2NhbF9pZC54O1xuICAgICR7KCgpID0+IHtcbiAgICAgIGlmIChjICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGBsZXQgY09mZnNldCA9ICR7Yy5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldCgndmVjMihtLCBuKScsIG91dHB1dCl9OyB2YWx1ZSArPSAke1xuICAgICAgICAgIG91dHB1dC50eXBlLnZhbHVlXG4gICAgICAgIH0odW5pZm9ybXMuYmV0YSkgKiAke2MuZ2V0QnlPZmZzZXQoJ2NPZmZzZXQnKX07YDtcbiAgICAgIH1cbiAgICAgIHJldHVybiAnJztcbiAgICB9KSgpfVxuICAgIGlmIChtIDwgdW5pZm9ybXMuTSAmJiBuIDwgdW5pZm9ybXMuTikge1xuICAgICAgb3V0cHV0W20gKiB1bmlmb3Jtcy5OICsgbl0gPSB2YWx1ZTtcbiAgICB9XG4gIH1gO1xuICB9O1xuXG4gIGlmICh1c2VTaGFyZWQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ0dlbW1TaGFyZWQnLFxuICAgICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX1gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV0sXG4gICAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogbnVtVGlsZU4gKiBudW1UaWxlTSB9LFxuICAgICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgICB9KSxcbiAgICAgIGdldFNoYWRlclNvdXJjZTogZ2V0U2hhZGVyU291cmNlU2hhcmVkLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdHZW1tJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHthdHRyaWJ1dGVzLmNhY2hlS2V5fWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUdlbW1BdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogR2VtbUF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCB0cmFuc0EgPSBhdHRyaWJ1dGVzLnRyYW5zQSBhcyBib29sZWFuO1xuICBjb25zdCB0cmFuc0IgPSBhdHRyaWJ1dGVzLnRyYW5zQiBhcyBib29sZWFuO1xuICBjb25zdCBhbHBoYSA9IGF0dHJpYnV0ZXMuYWxwaGEgYXMgbnVtYmVyO1xuICBjb25zdCBiZXRhID0gYXR0cmlidXRlcy5iZXRhIGFzIG51bWJlcjtcbiAgcmV0dXJuIHtcbiAgICB0cmFuc0EsXG4gICAgdHJhbnNCLFxuICAgIGFscGhhLFxuICAgIGJldGEsXG4gICAgY2FjaGVLZXk6IGAke2F0dHJpYnV0ZXMudHJhbnNBfTske2F0dHJpYnV0ZXMudHJhbnNCfTske2F0dHJpYnV0ZXMuYWxwaGEgPT09IDF9YCxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZW1tID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBHZW1tQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVHZW1tUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsIEluZGljZXNIZWxwZXIsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmxldCBbaWR4TiwgaWR4QywgaWR4SCwgaWR4V10gPSBbMCwgMSwgMiwgM107IC8vIE5DSFdcbnR5cGUgTW9kZSA9ICdiaWxpbmVhcicgfCAnbmVhcmVzdCcgfCAnYmljdWJpYyc7XG50eXBlIFBhZGRpbmdNb2RlID0gJ3plcm9zJyB8ICdib3JkZXInIHwgJ3JlZmxlY3Rpb24nO1xudHlwZSBGb3JtYXQgPSAnTkhXQycgfCAnTkNIVyc7XG5leHBvcnQgaW50ZXJmYWNlIEdyaWRTYW1wZUF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICBhbGlnbkNvcm5lcnM6IG51bWJlcjtcbiAgbW9kZTogTW9kZTtcbiAgcGFkZGluZ01vZGU6IFBhZGRpbmdNb2RlO1xuICBmb3JtYXQ6IEZvcm1hdDtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgIHRocm93IG5ldyBFcnJvcignb25seSA0LUQgdGVuc29yIGlzIHN1cHBvcnRlZC4nKTtcbiAgfVxuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoICE9PSBpbnB1dHNbMV0uZGltcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0IGRpbWVuc2lvbnMgbXVzdCBiZSBlcXVhbCB0byBncmlkIGRpbWVuc2lvbnMnKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAyICE9PSBpbnB1dHNbMV0uZGltc1tpbnB1dHNbMV0uZGltcy5sZW5ndGggLSAxXSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgbGFzdCBkaW1lbnNpb24gb2YgZ3JpZCBtdXN0IGJlIGVxdWFsIHRvICR7aW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMn1gKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0uZGltc1swXSAhPT0gaW5wdXRzWzFdLmRpbXNbMF0pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dyaWQgYmF0Y2ggc2l6ZSBtdXN0IG1hdGNoIGlucHV0IGJhdGNoIHNpemUnKTtcbiAgfVxufTtcblxuY29uc3QgZ3NHZXRDdWJpY0NvZWZmcyA9IGBcbiAgZm4gZ3NfZ2V0X2N1YmljX2NvZWZmcyh4OiBmMzIpIC0+IHZlYzQ8ZjMyPiB7XG4gICAgbGV0IGN1YmljX2FscGhhID0gLTAuNzVmO1xuICAgIGxldCB4X2FicyA9IGFicyh4KTtcbiAgICB2YXIgY29lZmZzOiB2ZWM0PGYzMj47XG4gICAgY29lZmZzWzBdID0gKCgoY3ViaWNfYWxwaGEgKiAoeF9hYnMgKyAxKSAtIDUgKiBjdWJpY19hbHBoYSkgKiAoeF9hYnMgKyAxKSArIDggKiBjdWJpY19hbHBoYSkgKiAoeF9hYnMgKyAxKSAtIDQgKiBjdWJpY19hbHBoYSk7XG4gICAgY29lZmZzWzFdID0gKCgoY3ViaWNfYWxwaGEgKyAyKSAqIHhfYWJzIC0gKGN1YmljX2FscGhhICsgMykpICogeF9hYnMgKiB4X2FicyArIDEpO1xuICAgIGNvZWZmc1syXSA9ICgoKGN1YmljX2FscGhhICsgMikgKiAoMSAtIHhfYWJzKSAtIChjdWJpY19hbHBoYSArIDMpKSAqICgxIC0geF9hYnMpICogKDEgLSB4X2FicykgKyAxKTtcbiAgICBjb2VmZnNbM10gPSAoKChjdWJpY19hbHBoYSAqICgyIC0geF9hYnMpIC0gNSAqIGN1YmljX2FscGhhKSAqICgyIC0geF9hYnMpICsgOCAqIGN1YmljX2FscGhhKSAqICgyIC0geF9hYnMpIC0gNCAqIGN1YmljX2FscGhhKTtcbiAgICByZXR1cm4gY29lZmZzO1xuICB9XG5gO1xuXG5jb25zdCBnc0JpY3ViaWNJbnRlcnBvbGF0ZSA9IChkYXRhVHlwZTogc3RyaW5nKTogc3RyaW5nID0+IGBcbiAgZm4gZ3NfYmljdWJpY19pbnRlcnBvbGF0ZShwOiBtYXQ0eDQ8JHtkYXRhVHlwZX0+LCB4OiBmMzIsIHk6IGYzMikgLT4gJHtkYXRhVHlwZX0ge1xuICAgIHZhciB2OiB2ZWM0PGYzMj47XG4gICAgdmFyIGNvZWZmcyA9IGdzX2dldF9jdWJpY19jb2VmZnMoeCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCA0OyBpKyspIHtcbiAgICAgIHZbaV0gPSBjb2VmZnNbMF0gKiBwW2ldWzBdICsgY29lZmZzWzFdICogcFtpXVsxXSArIGNvZWZmc1syXSAqIHBbaV1bMl0gKyBjb2VmZnNbM10gKiBwW2ldWzNdO1xuICAgIH1cbiAgICBjb2VmZnMgPSBnc19nZXRfY3ViaWNfY29lZmZzKHkpO1xuICAgIGxldCBwaXhlbCA9ICR7ZGF0YVR5cGV9KGNvZWZmc1swXSAqIHZbMF0gKyBjb2VmZnNbMV0gKiB2WzFdICsgY29lZmZzWzJdICogdlsyXSArIGNvZWZmc1szXSAqIHZbM10pO1xuICAgIHJldHVybiBwaXhlbDtcbiAgfVxuYDtcblxuY29uc3QgZ3NEZW5vcm1hbGl6ZSA9IChhdHRyaWJ1dGVzOiBHcmlkU2FtcGVBdHRyaWJ1dGVzKTogc3RyaW5nID0+IGBcbiAgZm4gZ3NfZGVub3JtYWxpemUobjogZjMyLCBsZW5ndGg6IGkzMikgLT4gZjMyIHtcbiAgICAke1xuICAgICAgYXR0cmlidXRlcy5hbGlnbkNvcm5lcnMgPT09IDBcbiAgICAgICAgPyBgXG4gICAgLy8gYWxpZ25Db3JuZXJzOiBmYWxzZSA9PiBbLTEsIDFdIHRvIFstMC41LCBsZW5ndGggLSAwLjVdXG4gICAgcmV0dXJuICgobiArIDEuMCkgKiBmMzIobGVuZ3RoKSAtIDEuMCkgLyAyLjA7XG4gICAgYFxuICAgICAgICA6IGBcbiAgICAvLyBhbGlnbkNvcm5lcnM6IHRydWUgPT4gWy0xLCAxXSB0byBbMCwgbGVuZ3RoIC0gMV1cbiAgICByZXR1cm4gKG4gKyAxLjApIC8gMi4wICogKGYzMihsZW5ndGggLSAxKSk7XG4gICAgYFxuICAgIH1cbiAgfVxuYDtcblxuY29uc3QgZ3NSZWZsZWN0ID0gKGF0dHJpYnV0ZXM6IEdyaWRTYW1wZUF0dHJpYnV0ZXMpOiBzdHJpbmcgPT4gYFxuICAke1xuICAgIGF0dHJpYnV0ZXMucGFkZGluZ01vZGUgPT09ICdyZWZsZWN0aW9uJ1xuICAgICAgPyBgXG4gICAgICBmbiBnc19yZWZsZWN0KHg6IGkzMiwgeF9taW46IGYzMiwgeF9tYXg6IGYzMikgLT4gdTMyIHtcbiAgICAgICAgdmFyIGR4ID0gMC4wO1xuICAgICAgICB2YXIgZnggPSBmMzIoeCk7XG4gICAgICAgIGxldCByYW5nZSA9IHhfbWF4IC0geF9taW47XG4gICAgICAgIGlmIChmeCA8IHhfbWluKSB7XG4gICAgICAgICAgZHggPSB4X21pbiAtIGZ4O1xuICAgICAgICAgIGxldCBuID0gdTMyKGR4IC8gcmFuZ2UpO1xuICAgICAgICAgIGxldCByID0gZHggLSBmMzIobikgKiByYW5nZTtcbiAgICAgICAgICBpZiAobiAlIDIgPT0gMCkge1xuICAgICAgICAgICAgZnggPSB4X21pbiArIHI7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZ4ID0geF9tYXggLSByO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChmeCA+IHhfbWF4KSB7XG4gICAgICAgICAgZHggPSBmeCAtIHhfbWF4O1xuICAgICAgICAgIGxldCBuID0gdTMyKGR4IC8gcmFuZ2UpO1xuICAgICAgICAgIGxldCByID0gZHggLSBmMzIobikgKiByYW5nZTtcbiAgICAgICAgICBpZiAobiAlIDIgPT0gMCkge1xuICAgICAgICAgICAgZnggPSB4X21heCAtIHI7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZ4ID0geF9taW4gKyByO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdTMyKGZ4KTtcbiAgICAgIH1gXG4gICAgICA6ICcnXG4gIH1cbmA7XG5cbmNvbnN0IHBpeGVsQXRHcmlkID0gKGlucHV0OiBJbmRpY2VzSGVscGVyLCBkYXRhVHlwZTogc3RyaW5nLCBhdHRyaWJ1dGVzOiBHcmlkU2FtcGVBdHRyaWJ1dGVzKTogc3RyaW5nID0+XG4gIGBcbiAgZm4gcGl4ZWxfYXRfZ3JpZChyOiBpMzIsIGM6IGkzMiwgSDogaTMyLCBXOiBpMzIsIGJhdGNoOiB1MzIsIGNoYW5uZWw6IHUzMiwgYm9yZGVyOiB2ZWM0PGYzMj4pIC0+ICR7ZGF0YVR5cGV9IHtcbiAgICAgdmFyIHBpeGVsID0gJHtkYXRhVHlwZX0oMCk7XG4gICAgIHZhciBpbmRpY2VzID0gdmVjNDx1MzI+KDApO1xuICAgICBpbmRpY2VzWyR7aWR4Tn1dID0gYmF0Y2g7XG4gICAgIGluZGljZXNbJHtpZHhDfV0gPSBjaGFubmVsO2AgK1xuICAoKCkgPT4ge1xuICAgIHN3aXRjaCAoYXR0cmlidXRlcy5wYWRkaW5nTW9kZSkge1xuICAgICAgY2FzZSAnemVyb3MnOlxuICAgICAgICByZXR1cm4gYFxuICAgICAgICAgIGlmIChyID49IDAgJiYgciA8IEggJiYgYyA+PTAgJiYgYyA8IFcpIHtcbiAgICAgICAgICAgIGluZGljZXNbJHtpZHhIfV0gPSB1MzIocik7XG4gICAgICAgICAgICBpbmRpY2VzWyR7aWR4V31dID0gdTMyKGMpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJHtkYXRhVHlwZX0oMCk7XG4gICAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgY2FzZSAnYm9yZGVyJzpcbiAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICBpbmRpY2VzWyR7aWR4SH1dID0gdTMyKGNsYW1wKHIsIDAsIEggLSAxKSk7XG4gICAgICAgICAgaW5kaWNlc1ske2lkeFd9XSA9IHUzMihjbGFtcChjLCAwLCBXIC0gMSkpO1xuICAgICAgICBgO1xuICAgICAgY2FzZSAncmVmbGVjdGlvbic6XG4gICAgICAgIHJldHVybiBgXG4gICAgICAgICAgaW5kaWNlc1ske2lkeEh9XSA9IGdzX3JlZmxlY3QociwgYm9yZGVyWzFdLCBib3JkZXJbM10pO1xuICAgICAgICAgIGluZGljZXNbJHtpZHhXfV0gPSBnc19yZWZsZWN0KGMsIGJvcmRlclswXSwgYm9yZGVyWzJdKTtcbiAgICAgICAgYDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgcGFkZGluZyBtb2RlICR7YXR0cmlidXRlcy5wYWRkaW5nTW9kZX0gaXMgbm90IHN1cHBvcnRlZGApO1xuICAgIH1cbiAgfSkoKSArXG4gIGBcbiAgICByZXR1cm4gJHtpbnB1dC5nZXRCeUluZGljZXMoJ2luZGljZXMnKX07XG4gIH1cbmA7XG5cbmNvbnN0IGNvbXB1dGVQaXhlbCA9IChvdXRwdXQ6IEluZGljZXNIZWxwZXIsIGRhdGFUeXBlOiBzdHJpbmcsIGF0dHJpYnV0ZXM6IEdyaWRTYW1wZUF0dHJpYnV0ZXMpOiBzdHJpbmcgPT5cbiAgKCgpID0+IHtcbiAgICBzd2l0Y2ggKGF0dHJpYnV0ZXMubW9kZSkge1xuICAgICAgY2FzZSAnbmVhcmVzdCc6XG4gICAgICAgIHJldHVybiBgXG4gICAgICAgICAgbGV0IHJlc3VsdCA9IHBpeGVsX2F0X2dyaWQoaTMyKHJvdW5kKHkpKSwgaTMyKHJvdW5kKHgpKSwgSF9pbiwgV19pbiwgaW5kaWNlc1ske2lkeE59XSwgaW5kaWNlc1ske2lkeEN9XSwgYm9yZGVyKTtcbiAgICAgICAgYDtcbiAgICAgIGNhc2UgJ2JpbGluZWFyJzpcbiAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICBsZXQgeDEgPSBpMzIoZmxvb3IoeCkpO1xuICAgICAgICAgIGxldCB5MSA9IGkzMihmbG9vcih5KSk7XG4gICAgICAgICAgbGV0IHgyID0geDEgKyAxO1xuICAgICAgICAgIGxldCB5MiA9IHkxICsgMTtcblxuICAgICAgICAgIGxldCBwMTEgPSBwaXhlbF9hdF9ncmlkKHkxLCB4MSwgSF9pbiwgV19pbiwgaW5kaWNlc1ske2lkeE59XSwgaW5kaWNlc1ske2lkeEN9XSwgYm9yZGVyKTtcbiAgICAgICAgICBsZXQgcDEyID0gcGl4ZWxfYXRfZ3JpZCh5MSwgeDIsIEhfaW4sIFdfaW4sIGluZGljZXNbJHtpZHhOfV0sIGluZGljZXNbJHtpZHhDfV0sIGJvcmRlcik7XG4gICAgICAgICAgbGV0IHAyMSA9IHBpeGVsX2F0X2dyaWQoeTIsIHgxLCBIX2luLCBXX2luLCBpbmRpY2VzWyR7aWR4Tn1dLCBpbmRpY2VzWyR7aWR4Q31dLCBib3JkZXIpO1xuICAgICAgICAgIGxldCBwMjIgPSBwaXhlbF9hdF9ncmlkKHkyLCB4MiwgSF9pbiwgV19pbiwgaW5kaWNlc1ske2lkeE59XSwgaW5kaWNlc1ske2lkeEN9XSwgYm9yZGVyKTtcblxuICAgICAgICAgIGxldCBkeDIgPSAke2RhdGFUeXBlfShmMzIoeDIpIC0geCk7XG4gICAgICAgICAgbGV0IGR4MSA9ICR7ZGF0YVR5cGV9KHggLSBmMzIoeDEpKTtcbiAgICAgICAgICBsZXQgZHkyID0gJHtkYXRhVHlwZX0oZjMyKHkyKSAtIHkpO1xuICAgICAgICAgIGxldCBkeTEgPSAke2RhdGFUeXBlfSh5IC0gZjMyKHkxKSk7XG4gICAgICAgICAgbGV0IHJlc3VsdCA9IGR5MiAqIChkeDIgKiBwMTEgKyBkeDEgKiBwMTIpICsgZHkxICogKGR4MiAqIHAyMSArIGR4MSAqIHAyMik7XG4gICAgICAgIGA7XG4gICAgICBjYXNlICdiaWN1YmljJzpcbiAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICBsZXQgeDAgPSBpMzIoZmxvb3IoeCkpIC0gMTtcbiAgICAgICAgICBsZXQgeTAgPSBpMzIoZmxvb3IoeSkpIC0gMTtcbiAgICAgICAgICB2YXIgcDogbWF0NHg0PCR7ZGF0YVR5cGV9PjtcbiAgICAgICAgICBmb3IgKHZhciBoID0gMDsgaCA8IDQ7IGgrKykge1xuICAgICAgICAgICAgZm9yICh2YXIgdyA9IDA7IHcgPCA0OyB3KyspIHtcbiAgICAgICAgICAgICAgcFtoXVt3XSA9IHBpeGVsX2F0X2dyaWQoaCArIHkwLCB3ICsgeDAsIEhfaW4sIFdfaW4sIGluZGljZXNbJHtpZHhOfV0sIGluZGljZXNbJHtpZHhDfV0sIGJvcmRlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbGV0IGR4ID0geCAtIGYzMih4MCArIDEpO1xuICAgICAgICAgIGxldCBkeSA9IHkgLSBmMzIoeTAgKyAxKTtcbiAgICAgICAgICBsZXQgcmVzdWx0ID0gZ3NfYmljdWJpY19pbnRlcnBvbGF0ZShwLCBkeCwgZHkpO1xuICAgICAgICBgO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBtb2RlICR7YXR0cmlidXRlcy5tb2RlfSBpcyBub3Qgc3VwcG9ydGVkYCk7XG4gICAgfVxuICB9KSgpICsgYCR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3Jlc3VsdCcpfWA7XG5cbmNvbnN0IGNyZWF0ZUdyaWRTYW1wbGVQcm9ncmFtSW5mbyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogR3JpZFNhbXBlQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgeCA9IGlucHV0VmFyaWFibGUoJ3gnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zLmxlbmd0aCk7XG4gIC8vIGRpc2NhcmQgbGFzdCBkaW1lbnNpb24gZm9yIHVzaW5nIHZlYzIgdG8gYWNjZXNzIGdyaWQgZGF0YVxuICBjb25zdCBncmlkU2hhcGUgPSBbaW5wdXRzWzFdLmRpbXNbMF0sIGlucHV0c1sxXS5kaW1zWzFdLCBpbnB1dHNbMV0uZGltc1syXV07XG4gIGNvbnN0IGdyaWQgPSBpbnB1dFZhcmlhYmxlKCdncmlkJywgaW5wdXRzWzFdLmRhdGFUeXBlLCBncmlkU2hhcGUubGVuZ3RoLCAyKTtcbiAgbGV0IG91dHB1dFNoYXBlID0gW2lucHV0c1swXS5kaW1zWzBdLCBpbnB1dHNbMF0uZGltc1sxXSwgaW5wdXRzWzFdLmRpbXNbMV0sIGlucHV0c1sxXS5kaW1zWzJdXTtcbiAgaWYgKGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQycpIHtcbiAgICBvdXRwdXRTaGFwZSA9IFtpbnB1dHNbMF0uZGltc1swXSwgaW5wdXRzWzFdLmRpbXNbMV0sIGlucHV0c1sxXS5kaW1zWzJdLCBpbnB1dHNbMF0uZGltc1szXV07XG4gICAgW2lkeE4sIGlkeEMsIGlkeEgsIGlkeFddID0gWzAsIDMsIDEsIDJdO1xuICB9XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCk7XG4gIGNvbnN0IGRhdGFUeXBlID0geC50eXBlLnZhbHVlO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1swXS5kaW1zLCBncmlkU2hhcGUsIG91dHB1dFNoYXBlKSxcbiAgXTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcbiAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3JtKCdvdXRwdXRfc2l6ZScsICd1MzInKS5kZWNsYXJlVmFyaWFibGVzKHgsIGdyaWQsIG91dHB1dCl9XG4gICR7Z3NHZXRDdWJpY0NvZWZmc31cbiAgJHtnc0JpY3ViaWNJbnRlcnBvbGF0ZShkYXRhVHlwZSl9XG4gICR7Z3NEZW5vcm1hbGl6ZShhdHRyaWJ1dGVzKX1cbiAgJHtnc1JlZmxlY3QoYXR0cmlidXRlcyl9XG4gICR7cGl4ZWxBdEdyaWQoeCwgZGF0YVR5cGUsIGF0dHJpYnV0ZXMpfVxuXG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgICBsZXQgSF9pbiA9IGkzMih1bmlmb3Jtcy54X3NoYXBlWyR7aWR4SH1dKTtcbiAgICAgIGxldCBXX2luID0gaTMyKHVuaWZvcm1zLnhfc2hhcGVbJHtpZHhXfV0pO1xuXG4gICAgICAke1xuICAgICAgICBhdHRyaWJ1dGVzLmFsaWduQ29ybmVycyA9PT0gMFxuICAgICAgICAgID8gYFxuICAgICAgbGV0IHhfbWluID0gLTAuNTtcbiAgICAgIGxldCB4X21heCA9IGYzMihXX2luKSAtIDAuNTtcbiAgICAgIGxldCB5X21pbiA9IC0wLjU7XG4gICAgICBsZXQgeV9tYXggPSBmMzIoSF9pbikgLSAwLjU7XG4gICAgICBgXG4gICAgICAgICAgOiBgXG4gICAgICBsZXQgeF9taW4gPSAwLjA7XG4gICAgICBsZXQgeF9tYXggPSBmMzIoV19pbikgLSAxLjA7XG4gICAgICBsZXQgeV9taW4gPSAwLjA7XG4gICAgICBsZXQgeV9tYXggPSBmMzIoSF9pbikgLSAxLjA7XG4gICAgICBgXG4gICAgICB9O1xuICAgICAgbGV0IGJvcmRlciA9IHZlYzQ8ZjMyPih4X21pbiwgeV9taW4sIHhfbWF4LCB5X21heCk7XG5cbiAgICAgIGxldCBpbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgICAgdmFyIGdyaWRfaW5kaWNlcyA9IHZlYzM8dTMyPihpbmRpY2VzWyR7aWR4Tn1dLCBpbmRpY2VzWyR7aWR4SH1dLCBpbmRpY2VzWyR7aWR4V31dKTtcbiAgICAgIGxldCBueHkgPSAke2dyaWQuZ2V0QnlJbmRpY2VzKCdncmlkX2luZGljZXMnKX07XG4gICAgICB2YXIgeCA9IGdzX2Rlbm9ybWFsaXplKGYzMihueHlbMF0pLCBXX2luKTtcbiAgICAgIHZhciB5ID0gZ3NfZGVub3JtYWxpemUoZjMyKG54eVsxXSksIEhfaW4pO1xuXG4gICAgICAke2NvbXB1dGVQaXhlbChvdXRwdXQsIGRhdGFUeXBlLCBhdHRyaWJ1dGVzKX1cbiAgfWA7XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnR3JpZFNhbXBsZScsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX1gLCBpbnB1dERlcGVuZGVuY2llczogWyd0eXBlJywgJ3R5cGUnXSB9LFxuICAgIGdldFJ1bkRhdGE6IChpbnB1dHMpID0+IHtcbiAgICAgIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgICB9O1xuICAgIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGdyaWRTYW1wbGUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEdyaWRTYW1wZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlR3JpZFNhbXBsZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKSk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VHcmlkU2FtcGxlQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEdyaWRTYW1wZUF0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtcbiAgICBhbGlnbkNvcm5lcnM6IGF0dHJpYnV0ZXMuYWxpZ25fY29ybmVycyBhcyBudW1iZXIsXG4gICAgbW9kZTogYXR0cmlidXRlcy5tb2RlIGFzIE1vZGUsXG4gICAgcGFkZGluZ01vZGU6IGF0dHJpYnV0ZXMucGFkZGluZ19tb2RlIGFzIFBhZGRpbmdNb2RlLFxuICAgIGZvcm1hdDogYXR0cmlidXRlcy5mb3JtYXQgYXMgRm9ybWF0LFxuICB9KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIEdwdURhdGFUeXBlLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgYXBwbHlBdHRlbnRpb24sXG4gIEF0dGVudGlvbkF0dHJzLFxuICBBdHRlbnRpb25NYXNrVHlwZSxcbiAgQXR0ZW50aW9uUGFyYW1ldGVycyxcbiAgQXR0ZW50aW9uUWt2Rm9ybWF0LFxufSBmcm9tICcuL2F0dGVudGlvbic7XG5pbXBvcnQgeyBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyLCBVbmlmb3Jtc0FycmF5VHlwZSB9IGZyb20gJy4vY29tbW9uJztcbmltcG9ydCB7IGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvLCBUcmFuc3Bvc2VBdHRyaWJ1dGVzIH0gZnJvbSAnLi90cmFuc3Bvc2UnO1xuXG5jb25zdCBnZXRJbnB1dCA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgaTogbnVtYmVyKSA9PlxuICBpbnB1dHMubGVuZ3RoID4gaSAmJiBpbnB1dHNbaV0uZGltcy5sZW5ndGggPiAwID8gaW5wdXRzW2ldIDogdW5kZWZpbmVkO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogQXR0ZW50aW9uQXR0cnMpOiBBdHRlbnRpb25QYXJhbWV0ZXJzID0+IHtcbiAgY29uc3QgcXVlcnkgPSBpbnB1dHNbMF07XG4gIGNvbnN0IGtleSA9IGdldElucHV0KGlucHV0cywgMSk7XG4gIGNvbnN0IHZhbHVlID0gZ2V0SW5wdXQoaW5wdXRzLCAyKTtcbiAgY29uc3QgYmlhcyA9IGdldElucHV0KGlucHV0cywgMyk7XG4gIGNvbnN0IGtleVBhZGRpbmdNYXNrID0gZ2V0SW5wdXQoaW5wdXRzLCA0KTtcbiAgY29uc3QgYXR0ZW50aW9uQmlhcyA9IGdldElucHV0KGlucHV0cywgNSk7XG4gIGNvbnN0IHBhc3RLZXkgPSBnZXRJbnB1dChpbnB1dHMsIDYpO1xuICBjb25zdCBwYXN0VmFsdWUgPSBnZXRJbnB1dChpbnB1dHMsIDcpO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBOb3RhdGlvbnM6XG4gIC8vICAgIEI6IGJhdGNoX3NpemVcbiAgLy8gICAgTjogbnVtX2hlYWRzXG4gIC8vICAgIEg6IGhlYWRfc2l6ZSBvZiBRIGFuZCBLXG4gIC8vICAgIEhfdjogaGVhZF9zaXplIG9mIFZcbiAgLy8gICAgRDogaGlkZGVuX3NpemUgZm9yIFEgYW5kIEssIHdoZXJlIEQgPSBOICogSFxuICAvLyAgICBEX3Y6IGhpZGRlbl9zaXplIG9mIFYsIHdoZXJlIERfdiA9IE4gKiBIX3ZcbiAgLy8gICAgUzogcV9zZXF1ZW5jZV9sZW5ndGhcbiAgLy8gICAgUDogcGFzdF9zZXF1ZW5jZV9sZW5ndGggb2Yga3YgY2FjaGVcbiAgLy8gICAgTDoga3Zfc2VxdWVuY2VfbGVuZ3RoXG4gIC8vICAgIFQ6IHRvdGFsX3NlcXVlbmNlX2xlbmd0aCA9IFAgKyBMXG4gIC8vICAgIE06IG1heF9zZXF1ZW5jZV9sZW5ndGggb2Yga3YgY2FjaGUgd2hlbiBwYXN0IGFuZCBwcmVzZW50IHNoYXJlIGJ1ZmZlclxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gTXVsdGlIZWFkQXR0ZW50aW9uIGlucHV0czpcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vICBRX0tfVl9CU05IIC0gbm8gcGFja2luZzpcbiAgLy8gICAgIHF1ZXJ5ICAgICAgICAgICAgKFEpICAgICAgIDogKEIsIFMsIEQpXG4gIC8vICAgICBrZXkgICAgICAgICAgICAgIChLKSAgICAgICA6IChCLCBMLCBEKVxuICAvLyAgICAgdmFsdWUgICAgICAgICAgICAoVikgICAgICAgOiAoQiwgTCwgRF92KVxuICAvLyAgUV9LX1ZfQlNOSF9CTlNIX0JOU0ggLSBjcm9zcyBhdHRlbnRpb24gKGt2IGNhY2hlIGlzIG5vdCB1c2VkLCBMID09IFQsIEQgPT0gRF92KTpcbiAgLy8gICAgIHF1ZXJ5ICAgICAgICAgICAgKFEpICAgICAgIDogKEIsIFMsIEQpXG4gIC8vICAgICBrZXkgICAgICAgICAgICAgIChLKSAgICAgICA6IChCLCBOLCBMLCBIKVxuICAvLyAgICAgdmFsdWUgICAgICAgICAgICAoVikgICAgICAgOiAoQiwgTiwgTCwgSF92KVxuICAvLyAgUV9LVl9CU05IX0JTTjJIIC0gcGFja2VkIGt2IChrdiBjYWNoZSBpcyBub3QgdXNlZCwgYmlhcyBpcyBub3QgYWxsb3dlZCBmb3IgcGFja2VkIGt2KTpcbiAgLy8gICAgIHF1ZXJ5ICAgICAgICAgICAgKFEpICAgICAgIDogKEIsIFMsIEQpXG4gIC8vICAgICBrZXkgICAgICAgICAgICAgIChLL1YpICAgICA6IChCLCBMLCBOLCAyLCBIKVxuICAvLyAgICAgdmFsdWUgICAgICAgICAgICAgICAgICAgICAgOiBOb25lXG4gIC8vICBRS1ZfQlNOM0ggLSBwYWNrZWQgcWt2IChrdiBjYWNoZSBpcyBub3QgdXNlZCwgUyA9PSBMLCBEID09IERfdik6XG4gIC8vICAgICBxdWVyeSAgICAgICAgICAgIChRL0svVikgICA6IChCLCBTLCBOLCAzLCBIKVxuICAvLyAgICAga2V5ICAgICAgICAgICAgICAgICAgICAgICAgOiBOb25lXG4gIC8vICAgICB2YWx1ZSAgICAgICAgICAgICAgICAgICAgICA6IE5vbmVcbiAgLy9cbiAgLy8gIE90aGVyIGlucHV0czpcbiAgLy8gICAgIGJpYXMgICAgICAgICAgICAgKFEvSy9WKSAgIDogTm9uZSBvciAoRCArIEQgKyBEX3YpXG4gIC8vICAgICBrZXlfcGFkZGluZ19tYXNrIChLL1YpICAgICA6IChCKSBvciAoMyAqIEIgKyAyKSBvciAoQiwgVCkgb3IgKEIsIFMsIFQpXG4gIC8vICAgICBhdHRlbnRpb25fYmlhcyAgICAgICAgICAgICA6IE5vbmUgb3IgKEIsIE4sIFMsIFQpLCAoMSwgTiwgUywgVCksIChCLCAxLCBTLCBUKSBvciAoMSwgMSwgUywgVClcbiAgLy8gICAgIHBhc3Rfa2V5ICAgICAgICAgICAgICAgICAgIDogKEIsIE4sIFAsIEgpIG9yIE5vbmUuIFBhc3Qgc3RhdGUgaXMgb25seSBhbGxvd2VkIGZvciBRX0tfVl9CU05ILlxuICAvLyAgICAgcGFzdF92YWx1ZSAgICAgICAgICAgICAgICAgOiAoQiwgTiwgUCwgSCkgb3IgTm9uZS4gUGFzdCBzdGF0ZSBpcyBvbmx5IGFsbG93ZWQgZm9yIFFfS19WX0JTTkguXG4gIC8vXG4gIC8vICBOb3QgU3VwcG9ydGVkOlxuICAvLyAgICAga2V5X3BhZGRpbmdfbWFzaywgcGFja2VkIGt2LCBwYWNrZWQgcWt2LCBhbmQgYnJvYWRjYXN0IGZvciBhdHRlbnRpb25fYmlhcy5cblxuICBpZiAocXVlcnkuZGltcy5sZW5ndGggIT09IDMgJiYgcXVlcnkuZGltcy5sZW5ndGggIT09IDUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IHF1ZXJ5IGlzIGV4cGVjdGVkIHRvIGhhdmUgMyBvciA1IGRpbWVuc2lvbnMnKTtcbiAgfVxuXG4gIGNvbnN0IGJhdGNoU2l6ZSA9IHF1ZXJ5LmRpbXNbMF07XG4gIGNvbnN0IHNlcXVlbmNlTGVuZ3RoID0gcXVlcnkuZGltc1sxXTtcbiAgY29uc3QgaGlkZGVuU2l6ZSA9IHF1ZXJ5LmRpbXMubGVuZ3RoID09PSAzID8gcXVlcnkuZGltc1syXSA6IGF0dHJpYnV0ZXMubnVtSGVhZHMgKiBxdWVyeS5kaW1zWzRdO1xuICBsZXQga3ZTZXF1ZW5jZUxlbmd0aCA9IHNlcXVlbmNlTGVuZ3RoO1xuXG4gIGxldCBwYXN0U2VxdWVuY2VMZW5ndGggPSAwO1xuICBsZXQgbWF4U2VxdWVuY2VMZW5ndGggPSAwO1xuICBjb25zdCBoZWFkU2l6ZSA9IE1hdGguZmxvb3IoaGlkZGVuU2l6ZSAvIGF0dHJpYnV0ZXMubnVtSGVhZHMpO1xuICBpZiAocGFzdEtleSAmJiBwYXN0VmFsdWUgJiYgU2hhcGVVdGlsLnNpemUocGFzdEtleS5kaW1zKSAmJiBTaGFwZVV0aWwuc2l6ZShwYXN0VmFsdWUuZGltcykpIHtcbiAgICBpZiAocGFzdEtleS5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInBhc3Rfa2V5XCIgaXMgZXhwZWN0ZWQgdG8gaGF2ZSA0IGRpbWVuc2lvbnMnKTtcbiAgICB9XG4gICAgaWYgKHBhc3RLZXkuZGltc1swXSAhPT0gYmF0Y2hTaXplIHx8IHBhc3RLZXkuZGltc1sxXSAhPT0gYXR0cmlidXRlcy5udW1IZWFkcyB8fCBwYXN0S2V5LmRpbXNbM10gIT09IGhlYWRTaXplKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicGFzdF9rZXlcIiBzaGFwZSAoYmF0Y2hfc2l6ZSwgbnVtX2hlYWRzLCBwYXN0X3NlcXVlbmNlX2xlbmd0aCwgaGVhZF9zaXplKScpO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICBwYXN0VmFsdWUuZGltc1swXSAhPT0gYmF0Y2hTaXplIHx8XG4gICAgICBwYXN0VmFsdWUuZGltc1sxXSAhPT0gYXR0cmlidXRlcy5udW1IZWFkcyB8fFxuICAgICAgcGFzdFZhbHVlLmRpbXNbM10gIT09IGhlYWRTaXplXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicGFzdF92YWx1ZVwiIHNoYXBlIChiYXRjaF9zaXplLCBudW1faGVhZHMsIHBhc3Rfc2VxdWVuY2VfbGVuZ3RoLCBoZWFkX3NpemUpJyk7XG4gICAgfVxuICAgIGlmIChwYXN0S2V5LmRpbXNbMl0gIT09IHBhc3RWYWx1ZS5kaW1zWzJdKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicGFzdF9rZXlcIiBhbmQgXCJwYXN0X3ZhbHVlXCIgc2hhbGwgaGF2ZSBzYW1lIGRpbSAyIChwYXN0X3NlcXVlbmNlX2xlbmd0aCknKTtcbiAgICB9XG4gICAgaWYgKHBhc3RWYWx1ZS5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInBhc3RfdmFsdWVcIiBpcyBleHBlY3RlZCB0byBoYXZlIDQgZGltZW5zaW9ucycpO1xuICAgIH1cbiAgICBwYXN0U2VxdWVuY2VMZW5ndGggPSBwYXN0S2V5LmRpbXNbMl07XG4gICAgbWF4U2VxdWVuY2VMZW5ndGggPSBwYXN0S2V5LmRpbXNbMl07XG4gIH0gZWxzZSBpZiAoKHBhc3RLZXkgJiYgU2hhcGVVdGlsLnNpemUocGFzdEtleS5kaW1zKSkgfHwgKHBhc3RWYWx1ZSAmJiBTaGFwZVV0aWwuc2l6ZShwYXN0VmFsdWUuZGltcykpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInBhc3Rfa2V5XCIgYW5kIFwicGFzdF92YWx1ZVwiIHNoYWxsIGJlIGJvdGggcHJlc2VudCBvciBib3RoIGFic2VudCcpO1xuICB9XG5cbiAgbGV0IHFrdkZvcm1hdDogQXR0ZW50aW9uUWt2Rm9ybWF0O1xuICBpZiAoa2V5ICYmIFNoYXBlVXRpbC5zaXplKGtleS5kaW1zKSA+IDApIHtcbiAgICBpZiAocXVlcnkuZGltcy5sZW5ndGggIT09IDMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJxdWVyeVwiIGlzIGV4cGVjdGVkIHRvIGhhdmUgMyBkaW1lbnNpb25zIHdoZW4ga2V5IGlzIGdpdmVuJyk7XG4gICAgfVxuICAgIGlmIChrZXkuZGltcy5sZW5ndGggPCAzIHx8IGtleS5kaW1zLmxlbmd0aCA+IDUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJrZXlcIiBpcyBleHBlY3RlZCB0byBoYXZlIDMsIDQsIG9yIDUgZGltZW5zaW9ucycpO1xuICAgIH1cbiAgICBpZiAocXVlcnkuZGltc1swXSAhPT0ga2V5LmRpbXNbMF0pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJxdWVyeVwiIGFuZCBcImtleVwiIHNoYWxsIGhhdmUgc2FtZSBkaW0gMCAoYmF0Y2ggc2l6ZSknKTtcbiAgICB9XG5cbiAgICBpZiAoa2V5LmRpbXMubGVuZ3RoID09PSAzKSB7XG4gICAgICBpZiAoa2V5LmRpbXNbMl0gIT09IHF1ZXJ5LmRpbXNbMl0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInF1ZXJ5XCIgYW5kIFwia2V5XCIgc2hhbGwgaGF2ZSBzYW1lIGRpbSAyIChoaWRkZW5fc2l6ZSknKTtcbiAgICAgIH1cbiAgICAgIHFrdkZvcm1hdCA9IEF0dGVudGlvblFrdkZvcm1hdC5xa3ZCU05IO1xuICAgICAga3ZTZXF1ZW5jZUxlbmd0aCA9IGtleS5kaW1zWzFdO1xuICAgIH0gZWxzZSBpZiAoa2V5LmRpbXMubGVuZ3RoID09PSA1KSB7XG4gICAgICBpZiAoa2V5LmRpbXNbMl0gIT09IGF0dHJpYnV0ZXMubnVtSGVhZHMgfHwga2V5LmRpbXNbM10gIT09IDIgfHwga2V5LmRpbXNbNF0gIT09IGhlYWRTaXplKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0IFwia2V5XCIgc2hhcGUgKGJhdGNoX3NpemUsIGt2X3NlcXVlbmNlX2xlbmd0aCwgbnVtX2hlYWRzLCAyLCBoZWFkX3NpemUpIGZvciBwYWNrZWQga3YnKTtcbiAgICAgIH1cbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdCBcInZhbHVlXCIgYmUgbm9uZSB3aGVuIFwia2V5XCIgaGFzIHBhY2tlZCBrdiBmb3JtYXQuJyk7XG4gICAgICB9XG4gICAgICBxa3ZGb3JtYXQgPSBBdHRlbnRpb25Ra3ZGb3JtYXQucUt2QlNOSHhCU04ySDtcbiAgICAgIGt2U2VxdWVuY2VMZW5ndGggPSBrZXkuZGltc1sxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8ga2V5X2RpbXMuc2l6ZSgpID09IDQgKGNyb3NzLWF0dGVudGlvbiB3aXRoIHBhc3Rfa2V5KVxuICAgICAgaWYgKGtleS5kaW1zWzFdICE9PSBhdHRyaWJ1dGVzLm51bUhlYWRzIHx8IGtleS5kaW1zWzNdICE9PSBoZWFkU2l6ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdCBcImtleVwiIHNoYXBlIChiYXRjaF9zaXplLCBudW1faGVhZHMsIGt2X3NlcXVlbmNlX2xlbmd0aCwgaGVhZF9zaXplKSBmb3IgcGFzdF9rZXknKTtcbiAgICAgIH1cblxuICAgICAgcWt2Rm9ybWF0ID0gQXR0ZW50aW9uUWt2Rm9ybWF0LnVua25vd247IC8vIFFfS19WX0JTTkhfQk5TSF9CTlNIXG4gICAgICBrdlNlcXVlbmNlTGVuZ3RoID0ga2V5LmRpbXNbMl07XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIHBhY2tlZCBRS1ZcbiAgICBpZiAocXVlcnkuZGltcy5sZW5ndGggIT09IDUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJxdWVyeVwiIGlzIGV4cGVjdGVkIHRvIGhhdmUgNSBkaW1lbnNpb25zIHdoZW4ga2V5IGlzIGVtcHR5Jyk7XG4gICAgfVxuICAgIGlmIChxdWVyeS5kaW1zWzJdICE9PSBhdHRyaWJ1dGVzLm51bUhlYWRzIHx8IHF1ZXJ5LmRpbXNbM10gIT09IDMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0IFwicXVlcnlcIiBzaGFwZSAoYmF0Y2hfc2l6ZSwga3Zfc2VxdWVuY2VfbGVuZ3RoLCBudW1faGVhZHMsIDMsIGhlYWRfc2l6ZSkgZm9yIHBhY2tlZCBrdicpO1xuICAgIH1cblxuICAgIHFrdkZvcm1hdCA9IEF0dGVudGlvblFrdkZvcm1hdC5xa3ZCU04zSDtcbiAgfVxuXG4gIGlmIChiaWFzICYmIFNoYXBlVXRpbC5zaXplKGJpYXMuZGltcykgPiAwKSB7XG4gICAgaWYgKGJpYXMuZGltcy5sZW5ndGggIT09IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJiaWFzXCIgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAxIGRpbWVuc2lvbicpO1xuICAgIH1cblxuICAgIGlmIChrZXkpIHtcbiAgICAgIGlmIChrZXkuZGltcy5sZW5ndGggPT09IDUgJiYga2V5LmRpbXNbM10gPT09IDIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdiaWFzIGlzIG5vdCBhbGxvd2VkIGZvciBwYWNrZWQga3YuJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29uc3QgdG90YWxTZXF1ZW5jZUxlbmd0aCA9IHBhc3RTZXF1ZW5jZUxlbmd0aCArIGt2U2VxdWVuY2VMZW5ndGg7XG5cbiAgbGV0IG1hc2tUeXBlOiBBdHRlbnRpb25NYXNrVHlwZSA9IEF0dGVudGlvbk1hc2tUeXBlLm5vbmU7XG4gIGlmIChrZXlQYWRkaW5nTWFzayAmJiBTaGFwZVV0aWwuc2l6ZShrZXlQYWRkaW5nTWFzay5kaW1zKSA+IDApIHtcbiAgICBtYXNrVHlwZSA9IEF0dGVudGlvbk1hc2tUeXBlLm1hc2tVbmtub3duO1xuICAgIGNvbnN0IG1hc2tEaW1zID0ga2V5UGFkZGluZ01hc2suZGltcztcbiAgICBpZiAobWFza0RpbXMubGVuZ3RoID09PSAxKSB7XG4gICAgICBpZiAobWFza0RpbXNbMF0gPT09IGJhdGNoU2l6ZSkge1xuICAgICAgICBtYXNrVHlwZSA9IEF0dGVudGlvbk1hc2tUeXBlLm1hc2sxZEtleVNlcUxlbjtcbiAgICAgIH0gZWxzZSBpZiAobWFza0RpbXNbMF0gPT09IDMgKiBiYXRjaFNpemUgKyAyKSB7XG4gICAgICAgIG1hc2tUeXBlID0gQXR0ZW50aW9uTWFza1R5cGUubWFzazFES2V5U2VxTGVuU3RhcnQ7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChtYXNrRGltcy5sZW5ndGggPT09IDIgJiYgbWFza0RpbXNbMF0gPT09IGJhdGNoU2l6ZSAmJiBtYXNrRGltc1sxXSA9PT0gdG90YWxTZXF1ZW5jZUxlbmd0aCkge1xuICAgICAgbWFza1R5cGUgPSBBdHRlbnRpb25NYXNrVHlwZS5tYXNrMmRLZXlQYWRkaW5nO1xuICAgIH1cbiAgICBpZiAobWFza1R5cGUgPT09IEF0dGVudGlvbk1hc2tUeXBlLm1hc2tVbmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwia2V5X3BhZGRpbmdfbWFza1wiIHNoYXBlIHNoYWxsIGJlIChiYXRjaF9zaXplKSBvciAoYmF0Y2hfc2l6ZSwgdG90YWxfc2VxdWVuY2VfbGVuZ3RoKScpO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01hc2sgbm90IHN1cHBvcnRlZCcpO1xuICB9XG5cbiAgbGV0IHBhc3NQYXN0SW5LdiA9IGZhbHNlO1xuICBsZXQgdkhpZGRlblNpemUgPSBoaWRkZW5TaXplO1xuICBpZiAodmFsdWUgJiYgU2hhcGVVdGlsLnNpemUodmFsdWUuZGltcykgPiAwKSB7XG4gICAgaWYgKHZhbHVlLmRpbXMubGVuZ3RoICE9PSAzICYmIHZhbHVlLmRpbXMubGVuZ3RoICE9PSA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwidmFsdWVcIiBpcyBleHBlY3RlZCB0byBoYXZlIDMgb3IgNCBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgaWYgKHF1ZXJ5LmRpbXNbMF0gIT09IHZhbHVlLmRpbXNbMF0pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJxdWVyeVwiIGFuZCBcInZhbHVlXCIgc2hhbGwgaGF2ZSBzYW1lIGRpbSAwIChiYXRjaF9zaXplKScpO1xuICAgIH1cblxuICAgIGlmICh2YWx1ZS5kaW1zLmxlbmd0aCA9PT0gMykge1xuICAgICAgaWYgKGt2U2VxdWVuY2VMZW5ndGggIT09IHZhbHVlLmRpbXNbMV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcImtleVwiIGFuZCBcInZhbHVlXCIgc2hhbGwgaGF2ZSB0aGUgc2FtZSBkaW0gMSAoa3Zfc2VxdWVuY2VfbGVuZ3RoKScpO1xuICAgICAgfVxuICAgICAgdkhpZGRlblNpemUgPSB2YWx1ZS5kaW1zWzJdO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBRX0tfVl9CU05IX0JOU0hfQk5TSFxuICAgICAgaWYgKGt2U2VxdWVuY2VMZW5ndGggIT09IHZhbHVlLmRpbXNbMl0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcImtleVwiIGFuZCBcInZhbHVlXCIgc2hhbGwgaGF2ZSB0aGUgc2FtZSBkaW0gMiAoa3Zfc2VxdWVuY2VfbGVuZ3RoKScpO1xuICAgICAgfVxuICAgICAgdkhpZGRlblNpemUgPSB2YWx1ZS5kaW1zWzFdICogdmFsdWUuZGltc1szXTtcbiAgICAgIHBhc3NQYXN0SW5LdiA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgYnJvYWRjYXN0UmVzUG9zQmlhcyA9IGZhbHNlO1xuXG4gIGlmIChrZXlQYWRkaW5nTWFzayAmJiBTaGFwZVV0aWwuc2l6ZShrZXlQYWRkaW5nTWFzay5kaW1zKSA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0tleSBwYWRkaW5nIG1hc2sgaXMgbm90IHN1cHBvcnRlZCcpO1xuICB9XG5cbiAgaWYgKGF0dGVudGlvbkJpYXMgJiYgU2hhcGVVdGlsLnNpemUoYXR0ZW50aW9uQmlhcy5kaW1zKSA+IDApIHtcbiAgICBpZiAoYXR0ZW50aW9uQmlhcy5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcImF0dGVudGlvbl9iaWFzXCIgaXMgZXhwZWN0ZWQgdG8gaGF2ZSA0IGRpbWVuc2lvbnMnKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGJyb2FkY2FzdGluZyB0aGUgZmlyc3QgYW5kIHNlY29uZCBkaW1lbnNpb25zIG9mIGF0dGVudGlvbl9iaWFzLlxuICAgIGlmIChcbiAgICAgIGF0dGVudGlvbkJpYXMuZGltc1swXSAhPT0gYmF0Y2hTaXplIHx8XG4gICAgICBhdHRlbnRpb25CaWFzLmRpbXNbMV0gIT09IGF0dHJpYnV0ZXMubnVtSGVhZHMgfHxcbiAgICAgIGF0dGVudGlvbkJpYXMuZGltc1syXSAhPT0gc2VxdWVuY2VMZW5ndGggfHxcbiAgICAgIGF0dGVudGlvbkJpYXMuZGltc1szXSAhPT0gdG90YWxTZXF1ZW5jZUxlbmd0aFxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3QgXCJhdHRlbnRpb25fYmlhc1wiIHNoYXBlIChiYXRjaF9zaXplLCBudW1faGVhZHMsIHNlcXVlbmNlX2xlbmd0aCwgdG90YWxfc2VxdWVuY2VfbGVuZ3RoKScpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgYmF0Y2hTaXplLFxuICAgIHNlcXVlbmNlTGVuZ3RoLFxuICAgIHBhc3RTZXF1ZW5jZUxlbmd0aCxcbiAgICBrdlNlcXVlbmNlTGVuZ3RoLFxuICAgIHRvdGFsU2VxdWVuY2VMZW5ndGgsXG4gICAgbWF4U2VxdWVuY2VMZW5ndGgsXG4gICAgaW5wdXRIaWRkZW5TaXplOiAwLFxuICAgIGhpZGRlblNpemUsXG4gICAgdkhpZGRlblNpemUsXG4gICAgaGVhZFNpemUsXG4gICAgdkhlYWRTaXplOiBNYXRoLmZsb29yKHZIaWRkZW5TaXplIC8gYXR0cmlidXRlcy5udW1IZWFkcyksXG4gICAgbnVtSGVhZHM6IGF0dHJpYnV0ZXMubnVtSGVhZHMsXG4gICAgaXNVbmlkaXJlY3Rpb25hbDogZmFsc2UsXG4gICAgcGFzdFByZXNlbnRTaGFyZUJ1ZmZlcjogZmFsc2UsXG4gICAgbWFza0ZpbHRlclZhbHVlOiBhdHRyaWJ1dGVzLm1hc2tGaWx0ZXJWYWx1ZSxcbiAgICBtYXNrVHlwZSxcbiAgICBzY2FsZTogYXR0cmlidXRlcy5zY2FsZSxcbiAgICBicm9hZGNhc3RSZXNQb3NCaWFzLFxuICAgIHBhc3NQYXN0SW5LdixcbiAgICBxa3ZGb3JtYXQsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VNdWx0aUhlYWRBdHRlbnRpb25BdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IEF0dGVudGlvbkF0dHJzKTogQXR0ZW50aW9uQXR0cnMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgLi4uYXR0cmlidXRlcyB9KTtcblxuY29uc3Qgd2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlOiBUcmFuc3Bvc2VBdHRyaWJ1dGVzID0gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgcGVybTogWzAsIDIsIDEsIDNdIH0pO1xuXG5jb25zdCBhZGRCaWFzVHJhbnNwb3NlID0gKFxuICBjb250ZXh0OiBDb21wdXRlQ29udGV4dCxcbiAgcWt2OiBUZW5zb3JWaWV3LFxuICBiaWFzOiBUZW5zb3JWaWV3LFxuICBiYXRjaFNpemU6IG51bWJlcixcbiAgc2VxdWVuY2VMZW5ndGg6IG51bWJlcixcbiAgaGlkZGVuU2l6ZTogbnVtYmVyLFxuICBiaWFzT2Zmc2V0OiBudW1iZXIsXG4pID0+IHtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBbYmF0Y2hTaXplLCBzZXF1ZW5jZUxlbmd0aCwgaGlkZGVuU2l6ZV07XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBiaWFzT2Zmc2V0IH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGhpZGRlblNpemUgfSxcbiAgXTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgncWt2X3dpdGhfYmlhcycsIHFrdi5kYXRhVHlwZSwgb3V0cHV0U2hhcGUpO1xuICAgIGNvbnN0IHFrdklucHV0ID0gaW5wdXRWYXJpYWJsZSgncWt2JywgcWt2LmRhdGFUeXBlLCBvdXRwdXRTaGFwZSk7XG4gICAgY29uc3QgYmlhc0lucHV0ID0gaW5wdXRWYXJpYWJsZSgnYmlhcycsIGJpYXMuZGF0YVR5cGUsIG91dHB1dFNoYXBlKTtcblxuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ291dHB1dF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2JpYXNfb2Zmc2V0JywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2hpZGRlbl9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICBdO1xuICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMocWt2SW5wdXQsIGJpYXNJbnB1dCwgb3V0cHV0KX1cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cbiAgICBsZXQgYmlhc19vZmZzZXRfaWR4ID0gKGdsb2JhbF9pZHggJSB1bmlmb3Jtcy5oaWRkZW5fc2l6ZSkgKyB1bmlmb3Jtcy5iaWFzX29mZnNldDtcblxuICAgIHFrdl93aXRoX2JpYXNbZ2xvYmFsX2lkeF0gPSBxa3ZbZ2xvYmFsX2lkeF0gKyBiaWFzW2JpYXNfb2Zmc2V0X2lkeF07XG4gIH1gO1xuICB9O1xuXG4gIHJldHVybiBjb250ZXh0LmNvbXB1dGUoXG4gICAge1xuICAgICAgbmFtZTogJ011bHRpSGVhZEF0dGVudGlvbkFkZEJpYXMnLFxuICAgICAgc2hhZGVyQ2FjaGU6IHsgaW5wdXREZXBlbmRlbmNpZXM6IFsndHlwZScsICd0eXBlJ10gfSxcbiAgICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogcWt2LmRhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCB9XSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgICB9KSxcbiAgICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICB9LFxuICAgIHsgaW5wdXRzOiBbcWt2LCBiaWFzXSwgb3V0cHV0czogWy0xXSB9LFxuICApWzBdO1xufTtcblxuZXhwb3J0IGNvbnN0IG1heWJlVHJhbnNwb3NlVG9CTlNIQW5kQWRkQmlhcyA9IChcbiAgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsXG4gIGJhdGNoU2l6ZTogbnVtYmVyLFxuICBudW1IZWFkczogbnVtYmVyLFxuICBzZXF1ZW5jZUxlbmd0aDogbnVtYmVyLFxuICBoZWFkU2l6ZTogbnVtYmVyLFxuICBpbnB1dDogVGVuc29yVmlldyxcbiAgYmlhcz86IFRlbnNvclZpZXcsXG4gIGJpYXNPZmZzZXQ/OiBudW1iZXIsXG4pID0+IHtcbiAgLy8gY29uc3QgbmV3RGltcyA9IFtdO1xuXG4gIGxldCByZXNoYXBlZElucHV0ID0gaW5wdXQ7XG4gIGlmICghKGJpYXMgJiYgU2hhcGVVdGlsLnNpemUoYmlhcy5kaW1zKSA+IDApKSB7XG4gICAgaWYgKGlucHV0LmRpbXMubGVuZ3RoID09PSAzKSB7XG4gICAgICByZXNoYXBlZElucHV0ID0gaW5wdXQucmVzaGFwZShbYmF0Y2hTaXplLCBzZXF1ZW5jZUxlbmd0aCwgbnVtSGVhZHMsIGhlYWRTaXplXSk7XG4gICAgfVxuICAgIGlmIChudW1IZWFkcyA9PT0gMSB8fCBzZXF1ZW5jZUxlbmd0aCA9PT0gMSkge1xuICAgICAgcmV0dXJuIHJlc2hhcGVkSW5wdXQ7XG4gICAgfVxuICAgIHJldHVybiBjb250ZXh0LmNvbXB1dGUoY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8ocmVzaGFwZWRJbnB1dCwgd2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlLnBlcm0pLCB7XG4gICAgICBpbnB1dHM6IFtyZXNoYXBlZElucHV0XSxcbiAgICAgIG91dHB1dHM6IFstMV0sXG4gICAgfSlbMF07XG4gIH0gZWxzZSB7XG4gICAgaWYgKHNlcXVlbmNlTGVuZ3RoID09PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FkZEJpYXNSZXNoYXBlIGlzIG5vdCBpbXBsZW1lbnRlZC4gUGxlYXNlIGV4cG9ydCB5b3VyIG1vZGVsIHdpdGggcGFja2VkIFFLViBvciBLVicpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXNoYXBlZElucHV0ID0gYWRkQmlhc1RyYW5zcG9zZShcbiAgICAgICAgY29udGV4dCxcbiAgICAgICAgaW5wdXQsXG4gICAgICAgIGJpYXMsXG4gICAgICAgIGJhdGNoU2l6ZSxcbiAgICAgICAgc2VxdWVuY2VMZW5ndGgsXG4gICAgICAgIG51bUhlYWRzICogaGVhZFNpemUsXG4gICAgICAgIGJpYXNPZmZzZXQhLFxuICAgICAgKTtcbiAgICAgIHJlc2hhcGVkSW5wdXQgPSByZXNoYXBlZElucHV0LnJlc2hhcGUoW2JhdGNoU2l6ZSwgc2VxdWVuY2VMZW5ndGgsIG51bUhlYWRzLCBoZWFkU2l6ZV0pO1xuICAgICAgaWYgKG51bUhlYWRzID09PSAxIHx8IHNlcXVlbmNlTGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiByZXNoYXBlZElucHV0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhyZXNoYXBlZElucHV0LCB3ZWlnaHRUcmFuc3Bvc2VBdHRyaWJ1dGUucGVybSksIHtcbiAgICAgICAgaW5wdXRzOiBbcmVzaGFwZWRJbnB1dF0sXG4gICAgICAgIG91dHB1dHM6IFstMV0sXG4gICAgICB9KVswXTtcbiAgICB9XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBtdWx0aUhlYWRBdHRlbnRpb24gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEF0dGVudGlvbkF0dHJzKTogdm9pZCA9PiB7XG4gIGNvbnN0IHBhcmFtcyA9IHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgY29uc3QgcXVlcnkgPSBjb250ZXh0LmlucHV0c1swXTtcbiAgY29uc3Qga2V5ID0gZ2V0SW5wdXQoY29udGV4dC5pbnB1dHMsIDEpO1xuICBjb25zdCB2YWx1ZSA9IGdldElucHV0KGNvbnRleHQuaW5wdXRzLCAyKTtcbiAgY29uc3QgYmlhcyA9IGdldElucHV0KGNvbnRleHQuaW5wdXRzLCAzKTtcbiAgY29uc3Qga2V5UGFkZGluZ01hc2sgPSBnZXRJbnB1dChjb250ZXh0LmlucHV0cywgNCk7XG4gIGNvbnN0IGF0dGVudGlvbkJpYXMgPSBnZXRJbnB1dChjb250ZXh0LmlucHV0cywgNSk7XG4gIGNvbnN0IHBhc3RLZXkgPSBnZXRJbnB1dChjb250ZXh0LmlucHV0cywgNik7XG4gIGNvbnN0IHBhc3RWYWx1ZSA9IGdldElucHV0KGNvbnRleHQuaW5wdXRzLCA3KTtcbiAgaWYgKHF1ZXJ5LmRpbXMubGVuZ3RoID09PSA1KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQYWNrZWQgUUtWIGlzIG5vdCBpbXBsZW1lbnRlZCcpO1xuICB9XG5cbiAgaWYgKGtleT8uZGltcy5sZW5ndGggPT09IDUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1BhY2tlZCBLViBpcyBub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxuXG4gIC8vIGFwcGx5QXR0ZW50aW9uIGV4cGVjdHMgQk5TSCBpbnB1dHNcbiAgY29uc3Qga3ZCTlNIID0ga2V5ICYmIHZhbHVlICYmIGtleS5kaW1zLmxlbmd0aCA9PT0gNCAmJiB2YWx1ZS5kaW1zLmxlbmd0aCA9PT0gNDtcblxuICBjb25zdCBRID0gbWF5YmVUcmFuc3Bvc2VUb0JOU0hBbmRBZGRCaWFzKFxuICAgIGNvbnRleHQsXG4gICAgcGFyYW1zLmJhdGNoU2l6ZSxcbiAgICBwYXJhbXMubnVtSGVhZHMsXG4gICAgcGFyYW1zLnNlcXVlbmNlTGVuZ3RoLFxuICAgIHBhcmFtcy5oZWFkU2l6ZSxcbiAgICBxdWVyeSxcbiAgICBiaWFzLFxuICAgIDAsXG4gICk7XG5cbiAgaWYgKGt2Qk5TSCkge1xuICAgIHJldHVybiBhcHBseUF0dGVudGlvbihjb250ZXh0LCBRLCBrZXksIHZhbHVlLCBrZXlQYWRkaW5nTWFzaywgdW5kZWZpbmVkLCBwYXN0S2V5LCBwYXN0VmFsdWUsIGF0dGVudGlvbkJpYXMsIHBhcmFtcyk7XG4gIH1cbiAgaWYgKCFrZXkgfHwgIXZhbHVlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdrZXkgYW5kIHZhbHVlIG11c3QgYmUgcHJvdmlkZWQnKTtcbiAgfVxuICBjb25zdCBLID0gbWF5YmVUcmFuc3Bvc2VUb0JOU0hBbmRBZGRCaWFzKFxuICAgIGNvbnRleHQsXG4gICAgcGFyYW1zLmJhdGNoU2l6ZSxcbiAgICBwYXJhbXMubnVtSGVhZHMsXG4gICAgcGFyYW1zLmt2U2VxdWVuY2VMZW5ndGgsXG4gICAgcGFyYW1zLmhlYWRTaXplLFxuICAgIGtleSxcbiAgICBiaWFzLFxuICAgIHBhcmFtcy5oaWRkZW5TaXplLFxuICApO1xuXG4gIGNvbnN0IFYgPSBtYXliZVRyYW5zcG9zZVRvQk5TSEFuZEFkZEJpYXMoXG4gICAgY29udGV4dCxcbiAgICBwYXJhbXMuYmF0Y2hTaXplLFxuICAgIHBhcmFtcy5udW1IZWFkcyxcbiAgICBwYXJhbXMua3ZTZXF1ZW5jZUxlbmd0aCxcbiAgICBwYXJhbXMudkhlYWRTaXplLFxuICAgIHZhbHVlLFxuICAgIGJpYXMsXG4gICAgMiAqIHBhcmFtcy5oaWRkZW5TaXplLFxuICApO1xuXG4gIGFwcGx5QXR0ZW50aW9uKGNvbnRleHQsIFEsIEssIFYsIGtleVBhZGRpbmdNYXNrLCB1bmRlZmluZWQsIHBhc3RLZXksIHBhc3RWYWx1ZSwgYXR0ZW50aW9uQmlhcywgcGFyYW1zKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSwgVGVuc29ySW5mbyB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGdldEVsZW1lbnRBdCxcbiAgSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbn0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNwbGl0QXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGF4aXM6IG51bWJlcjtcbiAgcmVhZG9ubHkgbnVtT3V0cHV0czogbnVtYmVyO1xuICByZWFkb25seSBzcGxpdFNpemVzOiBudW1iZXJbXTtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCA8IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3RvbyBmZXcgaW5wdXRzJyk7XG4gIH1cbn07XG5cbmNvbnN0IGNyZWF0ZVNwbGl0QXR0cmlidXRlc0Zyb21JbnB1dHMgPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBTcGxpdEF0dHJpYnV0ZXMsXG4pOiBTcGxpdEF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBzcGxpdFNpemVzOiBudW1iZXJbXSA9IFtdO1xuICBsZXQgbnVtT3V0cHV0czogbnVtYmVyID0gYXR0cmlidXRlcy5udW1PdXRwdXRzO1xuICBpZiAoaW5wdXRzWzFdLmRpbXNbMF0gPiAwKSB7XG4gICAgaW5wdXRzWzFdLmdldEJpZ0ludDY0QXJyYXkoKS5mb3JFYWNoKCh2KSA9PiBzcGxpdFNpemVzLnB1c2goTnVtYmVyKHYpKSk7XG4gICAgbnVtT3V0cHV0cyA9IHNwbGl0U2l6ZXMubGVuZ3RoO1xuICB9XG4gIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyBudW1PdXRwdXRzLCBheGlzOiBhdHRyaWJ1dGVzLmF4aXMsIHNwbGl0U2l6ZXMgfSk7XG59O1xuXG5jb25zdCBjYWxjdWxhdGVPdXRwdXRJbmRleEltcGwgPSAobnVtYmVyT2ZUZW5zb3JzOiBudW1iZXIpOiBzdHJpbmcgPT4gYFxuZm4gY2FsY3VsYXRlT3V0cHV0SW5kZXgoaW5kZXg6IHUzMikgLT4gdTMyIHtcbiAgICBmb3IgKHZhciBpOiB1MzIgPSAwdTsgaSA8ICR7bnVtYmVyT2ZUZW5zb3JzfXU7IGkgKz0gMXUgKSB7XG4gICAgaWYgKGluZGV4IDwgJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnNpemVfaW5fc3BsaXRfYXhpcycsICdpJywgbnVtYmVyT2ZUZW5zb3JzKX0pIHtcbiAgICAgICAgcmV0dXJuIGk7XG4gICAgfVxuICAgIH1cbiAgICByZXR1cm4gJHtudW1iZXJPZlRlbnNvcnN9dTtcbn1gO1xuY29uc3Qgd3JpdGVCdWZmZXJEYXRhSW1wbCA9IChvdXRwdXRzOiByZWFkb25seSBJbmRpY2VzSGVscGVyW10pID0+IHtcbiAgY29uc3QgbnVtYmVyT2ZUZW5zb3JzID0gb3V0cHV0cy5sZW5ndGg7XG4gIGNvbnN0IGNvZGVMaW5lczogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZlRlbnNvcnM7ICsraSkge1xuICAgIGNvbnN0IHJldHVyblNuaXBwZXQgPSBvdXRwdXRzW2ldLnNldEJ5SW5kaWNlcygnaW5kaWNlcycsICdpbnB1dFtnbG9iYWxfaWR4XScpO1xuICAgIGlmIChudW1iZXJPZlRlbnNvcnMgPT09IDEpIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKHJldHVyblNuaXBwZXQpO1xuICAgIH0gZWxzZSBpZiAoaSA9PT0gMCkge1xuICAgICAgY29kZUxpbmVzLnB1c2goYGlmIChvdXRwdXRfbnVtYmVyID09ICR7aX11KSB7ICR7cmV0dXJuU25pcHBldH0gfWApO1xuICAgIH0gZWxzZSBpZiAoaSA9PT0gbnVtYmVyT2ZUZW5zb3JzIC0gMSkge1xuICAgICAgY29kZUxpbmVzLnB1c2goYGVsc2UgeyAke3JldHVyblNuaXBwZXR9IH1gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZUxpbmVzLnB1c2goYGVsc2UgaWYgKG91dHB1dF9udW1iZXIgPT0gJHtpfSkgeyAke3JldHVyblNuaXBwZXR9IH1gKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGBcbiAgICAgIGZuIHdyaXRlQnVmZmVyRGF0YShvdXRwdXRfbnVtYmVyOiB1MzIsIGluZGljZXM6ICR7b3V0cHV0c1swXS50eXBlLmluZGljZXN9LCBnbG9iYWxfaWR4OiB1MzIpIHtcbiAgICAgICAgJHtjb2RlTGluZXMuam9pbignXFxuJyl9XG4gICAgICB9YDtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVTcGxpdFByb2dyYW1JbmZvID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBTcGxpdEF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgaW5wdXRTaXplID0gU2hhcGVVdGlsLnNpemUoaW5wdXRTaGFwZSk7XG4gIGNvbnN0IGRhdGFUeXBlID0gaW5wdXRzWzBdLmRhdGFUeXBlO1xuICBjb25zdCBheGlzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4aXMoYXR0cmlidXRlcy5heGlzLCBpbnB1dFNoYXBlLmxlbmd0aCk7XG4gIGNvbnN0IG91dHB1dHMgPSBuZXcgQXJyYXk8SW5kaWNlc0hlbHBlcj4oYXR0cmlidXRlcy5udW1PdXRwdXRzKTtcbiAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGRhdGFUeXBlLCBpbnB1dFNoYXBlLmxlbmd0aCk7XG4gIGNvbnN0IHNpemVJblNwbGl0QXhpcyA9IG5ldyBBcnJheTxudW1iZXI+KGF0dHJpYnV0ZXMubnVtT3V0cHV0cyk7XG4gIGNvbnN0IG91dHB1dHNUZW5zb3JJbmZvOiBUZW5zb3JJbmZvW10gPSBbXTtcbiAgY29uc3Qgb3V0cHV0U2hhcGVzOiBudW1iZXJbXVtdID0gW107XG4gIGxldCBwcmV2aW91c1N1bSA9IDA7XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFt7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogaW5wdXRTaXplIH1dO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dHJpYnV0ZXMubnVtT3V0cHV0czsgaSsrKSB7XG4gICAgcHJldmlvdXNTdW0gKz0gYXR0cmlidXRlcy5zcGxpdFNpemVzW2ldO1xuICAgIHNpemVJblNwbGl0QXhpc1tpXSA9IHByZXZpb3VzU3VtO1xuICAgIGNvbnN0IG91dHB1dFNoYXBlID0gaW5wdXRTaGFwZS5zbGljZSgpO1xuICAgIG91dHB1dFNoYXBlW2F4aXNdID0gYXR0cmlidXRlcy5zcGxpdFNpemVzW2ldO1xuICAgIG91dHB1dFNoYXBlcy5wdXNoKG91dHB1dFNoYXBlKTtcbiAgICBvdXRwdXRzW2ldID0gb3V0cHV0VmFyaWFibGUoYG91dHB1dCR7aX1gLCBkYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoKTtcbiAgICBvdXRwdXRzVGVuc29ySW5mby5wdXNoKHsgZGltczogb3V0cHV0U2hhcGVzW2ldLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH0pO1xuICB9XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBzaXplSW5TcGxpdEF4aXMgfSxcbiAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dFNoYXBlLCAuLi5vdXRwdXRTaGFwZXMpLFxuICApO1xuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcbiAgJHtzaGFkZXJIZWxwZXJcbiAgICAucmVnaXN0ZXJVbmlmb3JtKCdpbnB1dF9zaXplJywgJ3UzMicpXG4gICAgLnJlZ2lzdGVyVW5pZm9ybSgnc2l6ZV9pbl9zcGxpdF9heGlzJywgJ3UzMicsIHNpemVJblNwbGl0QXhpcy5sZW5ndGgpXG4gICAgLmRlY2xhcmVWYXJpYWJsZXMoaW5wdXQsIC4uLm91dHB1dHMpfVxuICAke2NhbGN1bGF0ZU91dHB1dEluZGV4SW1wbChzaXplSW5TcGxpdEF4aXMubGVuZ3RoKX1cbiAgJHt3cml0ZUJ1ZmZlckRhdGFJbXBsKG91dHB1dHMpfVxuXG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLmlucHV0X3NpemUnKX1cblxuICAgIHZhciBpbmRpY2VzID0gJHtpbnB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgdmFyIGluZGV4ID0gJHtpbnB1dC5pbmRpY2VzR2V0KCdpbmRpY2VzJywgYXhpcyl9O1xuICAgIGxldCBvdXRwdXRfbnVtYmVyID0gY2FsY3VsYXRlT3V0cHV0SW5kZXgoaW5kZXgpO1xuICAgIGlmIChvdXRwdXRfbnVtYmVyICE9IDApIHtcbiAgICAgIGluZGV4IC09ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5zaXplX2luX3NwbGl0X2F4aXMnLCAnb3V0cHV0X251bWJlciAtIDF1Jywgc2l6ZUluU3BsaXRBeGlzLmxlbmd0aCl9O1xuICAgICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbmRpY2VzJywgYXhpcywgJ2luZGV4Jyl9O1xuICAgIH1cbiAgICB3cml0ZUJ1ZmZlckRhdGEob3V0cHV0X251bWJlciwgaW5kaWNlcywgZ2xvYmFsX2lkeCk7XG4gIH1gO1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdTcGxpdCcsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYXR0cmlidXRlcy5jYWNoZUtleSwgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuayddIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBvdXRwdXRzVGVuc29ySW5mbyxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKGlucHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHNwbGl0ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBTcGxpdEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCB1cGRhdGVkQXR0cmlidXRlcyA9XG4gICAgY29udGV4dC5pbnB1dHMubGVuZ3RoID09PSAxID8gYXR0cmlidXRlcyA6IGNyZWF0ZVNwbGl0QXR0cmlidXRlc0Zyb21JbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlU3BsaXRQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgdXBkYXRlZEF0dHJpYnV0ZXMpLCB7IGlucHV0czogWzBdIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlU3BsaXRBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogU3BsaXRBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgYXhpcyA9IGF0dHJpYnV0ZXMuYXhpcyBhcyBudW1iZXI7XG4gIGNvbnN0IHNwbGl0U2l6ZXM6IG51bWJlcltdID0gYXR0cmlidXRlcy5zcGxpdFNpemVzIGFzIG51bWJlcltdO1xuICBjb25zdCBudW1PdXRwdXRzID0gKGF0dHJpYnV0ZXMubnVtT3V0cHV0cyBhcyBudW1iZXIpIDwgMCA/IHNwbGl0U2l6ZXMubGVuZ3RoIDogKGF0dHJpYnV0ZXMubnVtT3V0cHV0cyBhcyBudW1iZXIpO1xuICBpZiAobnVtT3V0cHV0cyAhPT0gc3BsaXRTaXplcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ251bU91dHB1dHMgYW5kIHNwbGl0U2l6ZXMgbGVuZ2ggbXVzdCBiZSBlcXVhbCcpO1xuICB9XG4gIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyBheGlzLCBudW1PdXRwdXRzLCBzcGxpdFNpemVzIH0pO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIsIFdPUktHUk9VUF9TSVpFIH0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJvdGFyeUVtYmVkZGluZ0F0dHJpYnV0ZXMge1xuICByZWFkb25seSBpbnRlcmxlYXZlZDogYm9vbGVhbjtcbiAgcmVhZG9ubHkgbnVtSGVhZHM6IG51bWJlcjtcbiAgcmVhZG9ubHkgcm90YXJ5RW1iZWRkaW5nRGltOiBudW1iZXI7XG4gIHJlYWRvbmx5IHNjYWxlOiBudW1iZXI7XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBSb3RhcnlFbWJlZGRpbmdBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IFtpbnB1dCwgcG9zaXRpb25JZHMsIGNvc0NhY2hlLCBzaW5DYWNoZV0gPSBpbnB1dHM7XG4gIGNvbnN0IHsgbnVtSGVhZHMsIHJvdGFyeUVtYmVkZGluZ0RpbSB9ID0gYXR0cmlidXRlcztcblxuICBpZiAoaW5wdXQuZGltcy5sZW5ndGggIT09IDMgJiYgaW5wdXQuZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYElucHV0ICd4JyBpcyBleHBlY3RlZCB0byBoYXZlIDMgb3IgNCBkaW1lbnNpb25zLCBnb3QgJHtpbnB1dC5kaW1zLmxlbmd0aH1gKTtcbiAgfVxuICBpZiAoXG4gICAgIVNoYXBlVXRpbC5hcmVFcXVhbChwb3NpdGlvbklkcy5kaW1zLCBbXSkgJiZcbiAgICAhU2hhcGVVdGlsLmFyZUVxdWFsKHBvc2l0aW9uSWRzLmRpbXMsIFsxXSkgJiZcbiAgICBwb3NpdGlvbklkcy5kaW1zLmxlbmd0aCAhPT0gMlxuICApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYElucHV0ICdwb3NpdGlvbl9pZHMnIGlzIGV4cGVjdGVkIHRvIGhhdmUgMCwgMSwgb3IgMiBkaW1lbnNpb25zLCBnb3QgJHtwb3NpdGlvbklkcy5kaW1zLmxlbmd0aH1gKTtcbiAgfVxuICBpZiAoY29zQ2FjaGUuZGltcy5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYElucHV0ICdjb3NfY2FjaGUnIGlzIGV4cGVjdGVkIHRvIGhhdmUgMiBkaW1lbnNpb25zLCBnb3QgJHtjb3NDYWNoZS5kaW1zLmxlbmd0aH1gKTtcbiAgfVxuICBpZiAoc2luQ2FjaGUuZGltcy5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYElucHV0ICdzaW5fY2FjaGUnIGlzIGV4cGVjdGVkIHRvIGhhdmUgMiBkaW1lbnNpb25zLCBnb3QgJHtzaW5DYWNoZS5kaW1zLmxlbmd0aH1gKTtcbiAgfVxuICBpZiAoIVNoYXBlVXRpbC5hcmVFcXVhbChjb3NDYWNoZS5kaW1zLCBzaW5DYWNoZS5kaW1zKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIklucHV0cyAnY29zX2NhY2hlJyBhbmQgJ3Npbl9jYWNoZScgYXJlIGV4cGVjdGVkIHRvIGhhdmUgdGhlIHNhbWUgc2hhcGVcIik7XG4gIH1cblxuICBpZiAocm90YXJ5RW1iZWRkaW5nRGltID4gMCAmJiBudW1IZWFkcyA9PT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignbnVtX2hlYWRzIG11c3QgYmUgcHJvdmlkZWQgaWYgcm90YXJ5X2VtYmVkZGluZ19kaW0gaXMgc3BlY2lmaWVkJyk7XG4gIH1cblxuICBjb25zdCBiYXRjaFNpemUgPSBpbnB1dC5kaW1zWzBdO1xuICBjb25zdCBzZXF1ZW5jZUxlbmd0aCA9IGlucHV0LmRpbXNbaW5wdXQuZGltcy5sZW5ndGggLSAyXTtcbiAgY29uc3QgbWF4U2VxdWVuY2VMZW5ndGggPSBjb3NDYWNoZS5kaW1zWzBdO1xuICBjb25zdCBoaWRkZW5TaXplID0gU2hhcGVVdGlsLnNpemVGcm9tRGltZW5zaW9uKGlucHV0LmRpbXMsIDEpIC8gc2VxdWVuY2VMZW5ndGg7XG4gIGNvbnN0IGhlYWRTaXplID0gcm90YXJ5RW1iZWRkaW5nRGltID09PSAwID8gY29zQ2FjaGUuZGltc1sxXSAqIDIgOiBoaWRkZW5TaXplIC8gbnVtSGVhZHM7XG4gIGlmIChyb3RhcnlFbWJlZGRpbmdEaW0gPiBoZWFkU2l6ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncm90YXJ5X2VtYmVkZGluZ19kaW0gbXVzdCBiZSBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gaGVhZF9zaXplJyk7XG4gIH1cblxuICBpZiAocG9zaXRpb25JZHMuZGltcy5sZW5ndGggPT09IDIpIHtcbiAgICBpZiAoYmF0Y2hTaXplICE9PSBwb3NpdGlvbklkcy5kaW1zWzBdKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYElucHV0ICdwb3NpdGlvbl9pZHMnIGRpbWVuc2lvbiAwIHNob3VsZCBiZSBvZiBzaXplIGJhdGNoX3NpemUsIGdvdCAke3Bvc2l0aW9uSWRzLmRpbXNbMF19YCk7XG4gICAgfVxuICAgIGlmIChzZXF1ZW5jZUxlbmd0aCAhPT0gcG9zaXRpb25JZHMuZGltc1sxXSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnB1dCAncG9zaXRpb25faWRzJyBkaW1lbnNpb24gMSBzaG91bGQgYmUgb2Ygc2l6ZSBzZXF1ZW5jZV9sZW5ndGgsIGdvdCAke3Bvc2l0aW9uSWRzLmRpbXNbMV19YCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGhlYWRTaXplIC8gMiAhPT0gY29zQ2FjaGUuZGltc1sxXSAmJiByb3RhcnlFbWJlZGRpbmdEaW0gLyAyICE9PSBjb3NDYWNoZS5kaW1zWzFdKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYElucHV0ICdjb3NfY2FjaGUnIGRpbWVuc2lvbiAxIHNob3VsZCBiZSBzYW1lIGFzIGhlYWRfc2l6ZSAvIDIgb3Igcm90YXJ5X2VtYmVkZGluZ19kaW0gLyAyLCBnb3QgJHtcbiAgICAgICAgY29zQ2FjaGUuZGltc1sxXVxuICAgICAgfWAsXG4gICAgKTtcbiAgfVxuXG4gIGlmIChzZXF1ZW5jZUxlbmd0aCA+IG1heFNlcXVlbmNlTGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdVcGRhdGluZyBjb3NfY2FjaGUgYW5kIHNpbl9jYWNoZSBpbiBSb3RhcnlFbWJlZGRpbmcgaXMgbm90IGN1cnJlbnRseSBzdXBwb3J0ZWQnKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVJvdGFyeUVtYmVkZGluZ1Byb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgeyBpbnRlcmxlYXZlZCwgbnVtSGVhZHMsIHJvdGFyeUVtYmVkZGluZ0RpbSwgc2NhbGUgfSA9IGF0dHJpYnV0ZXM7XG4gIGNvbnN0IGJhdGNoU2l6ZSA9IGlucHV0c1swXS5kaW1zWzBdO1xuICBjb25zdCBiYXRjaFN0cmlkZSA9IFNoYXBlVXRpbC5zaXplRnJvbURpbWVuc2lvbihpbnB1dHNbMF0uZGltcywgMSk7XG4gIGNvbnN0IHNlcXVlbmNlTGVuZ3RoID0gaW5wdXRzWzBdLmRpbXNbaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMl07XG4gIGNvbnN0IGhpZGRlblNpemUgPSBiYXRjaFN0cmlkZSAvIHNlcXVlbmNlTGVuZ3RoO1xuICBjb25zdCBoYWxmUm90YXJ5RW1iZWRkaW5nRGltID0gaW5wdXRzWzJdLmRpbXNbMV07XG4gIGNvbnN0IGhlYWRTaXplID0gcm90YXJ5RW1iZWRkaW5nRGltID09PSAwID8gaGFsZlJvdGFyeUVtYmVkZGluZ0RpbSAqIDIgOiBoaWRkZW5TaXplIC8gbnVtSGVhZHM7XG5cbiAgLy8gUm90YXJ5IGVtYmVkZGluZ3Mgd2lsbCBiZSBjYWxjdWxhdGVkIGluIGEgcGFpci13aXNlIGZhc2hpb24uIEluIGFjY29yZGFuY2UsIHVzZSB0aGUgc2hhcGVcbiAgLy8gW2JhdGNoIHNpemUsIHNlcXVlbmNlIGxlbmd0aCwgbnVtIG9mIGhlYWRzLCBudW0gb2YgcGFpcnMgdG8gcm90YXRlICsgbnVtIG9mIGRpbXMgdG8gY29weV1cbiAgLy8gdG8gdW5mb2xkIHRoZSBnbG9iYWwgaW5kZXggaW4gc2hhZGVyLlxuICBjb25zdCBnbG9iYWxTaGFwZSA9IG5ldyBBcnJheTxudW1iZXI+KFxuICAgIGJhdGNoU2l6ZSxcbiAgICBzZXF1ZW5jZUxlbmd0aCxcbiAgICBoaWRkZW5TaXplIC8gaGVhZFNpemUsXG4gICAgaGVhZFNpemUgLSBoYWxmUm90YXJ5RW1iZWRkaW5nRGltLFxuICApO1xuICBjb25zdCBnbG9iYWxTdHJpZGVzID0gU2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKGdsb2JhbFNoYXBlKTtcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogc2NhbGUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogZ2xvYmFsU2hhcGUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogZ2xvYmFsU3RyaWRlcyB9LFxuXG4gICAgLy8gc3RyaWRlcyBmb3IgYWRkcmVzc2luZyB0aGUgaW5wdXQvb3V0cHV0IHRlbnNvciwgaW4gcGVybXV0YXRlZCBvcmRlciB0byBhbGlnbiB3aXRoIHRoZSB1bmZvbGRlZCBnbG9iYWwgaW5kZXgsXG4gICAgLy8gaS5lLiBCU05IXG4gICAgLi4uKGlucHV0c1swXS5kaW1zLmxlbmd0aCA9PT0gM1xuICAgICAgPyBuZXcgQXJyYXk8UHJvZ3JhbVVuaWZvcm0+KHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBbYmF0Y2hTdHJpZGUsIGhpZGRlblNpemUsIGhlYWRTaXplLCAxXSB9KVxuICAgICAgOiBbXSksXG4gICAgLi4uKGlucHV0c1swXS5kaW1zLmxlbmd0aCA9PT0gNFxuICAgICAgPyBuZXcgQXJyYXk8UHJvZ3JhbVVuaWZvcm0+KHtcbiAgICAgICAgICB0eXBlOiBEYXRhVHlwZS51aW50MzIsXG4gICAgICAgICAgZGF0YTogW2JhdGNoU3RyaWRlLCBoZWFkU2l6ZSwgc2VxdWVuY2VMZW5ndGggKiBoZWFkU2l6ZSwgMV0sXG4gICAgICAgIH0pXG4gICAgICA6IFtdKSxcblxuICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1swXS5kaW1zLCBpbnB1dHNbMV0uZGltcywgaW5wdXRzWzJdLmRpbXMsIGlucHV0c1szXS5kaW1zLCBpbnB1dHNbMF0uZGltcyksXG4gIF07XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgaW5wdXQgPSBpbnB1dFZhcmlhYmxlKCdpbnB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBwb3NpdGlvbklkcyA9IGlucHV0VmFyaWFibGUoJ3Bvc2l0aW9uX2lkcycsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBjb3NDYWNoZSA9IGlucHV0VmFyaWFibGUoJ2Nvc19jYWNoZScsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBzaW5DYWNoZSA9IGlucHV0VmFyaWFibGUoJ3Npbl9jYWNoZScsIGlucHV0c1szXS5kYXRhVHlwZSwgaW5wdXRzWzNdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcy5sZW5ndGgpO1xuXG4gICAgc2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXMoW1xuICAgICAgeyBuYW1lOiAnc2NhbGUnLCB0eXBlOiAnZjMyJyB9LFxuICAgICAgeyBuYW1lOiAnZ2xvYmFsX3NoYXBlJywgdHlwZTogJ3UzMicsIGxlbmd0aDogZ2xvYmFsU2hhcGUubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdnbG9iYWxfc3RyaWRlcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGdsb2JhbFN0cmlkZXMubGVuZ3RoIH0sXG4gICAgICB7IG5hbWU6ICdpbnB1dF9vdXRwdXRfc3RyaWRlcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGdsb2JhbFN0cmlkZXMubGVuZ3RoIH0sXG4gICAgXSk7XG5cbiAgICByZXR1cm4gYFxuICAgICAgICAke3NoYWRlckhlbHBlci5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBwb3NpdGlvbklkcywgY29zQ2FjaGUsIHNpbkNhY2hlLCBvdXRwdXQpfVxuXG4gICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydChXT1JLR1JPVVBfU0laRSl9XG4gICAgICAgICAgbGV0IGhhbGZfcm90YXJ5X2VtYl9kaW0gPSB1bmlmb3Jtcy4ke2Nvc0NhY2hlLm5hbWV9X3NoYXBlWzFdO1xuICAgICAgICAgIGxldCBic25oID0gZ2xvYmFsX2lkeCAvIHVuaWZvcm1zLmdsb2JhbF9zdHJpZGVzICUgdW5pZm9ybXMuZ2xvYmFsX3NoYXBlO1xuICAgICAgICAgIGxldCBzaXplID0gdW5pZm9ybXMuZ2xvYmFsX3NoYXBlWzBdICogdW5pZm9ybXMuZ2xvYmFsX3N0cmlkZXNbMF07XG4gICAgICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygnc2l6ZScpfVxuXG4gICAgICAgICAgaWYgKGJzbmhbM10gPCBoYWxmX3JvdGFyeV9lbWJfZGltKSB7XG4gICAgICAgICAgICBsZXQgcG9zaXRpb25faWRzX2lkeCA9XG4gICAgICAgICAgICAgICAgJHtwb3NpdGlvbklkcy5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldCgnYnNuaC54eScsIG91dHB1dFZhcmlhYmxlKCcnLCBwb3NpdGlvbklkcy50eXBlLnRlbnNvciwgMikpfTtcbiAgICAgICAgICAgIGxldCBwb3NpdGlvbl9pZCA9XG4gICAgICAgICAgICAgICAgdTMyKCR7cG9zaXRpb25JZHMuZ2V0QnlPZmZzZXQoJ3Bvc2l0aW9uX2lkc19pZHgnKX0pICsgc2VsZWN0KDAsIGJzbmhbMV0sIHBvc2l0aW9uX2lkc19pZHggPT0gMCk7XG4gICAgICAgICAgICBsZXQgaSA9IGRvdChic25oLCB1bmlmb3Jtcy5pbnB1dF9vdXRwdXRfc3RyaWRlcykgKyBzZWxlY3QoMCwgYnNuaFszXSwgJHtpbnRlcmxlYXZlZH0pO1xuICAgICAgICAgICAgbGV0IGogPSBpICsgc2VsZWN0KGhhbGZfcm90YXJ5X2VtYl9kaW0sIDEsICR7aW50ZXJsZWF2ZWR9KTtcbiAgICAgICAgICAgIGxldCByZSA9ICR7aW5wdXQuZ2V0QnlPZmZzZXQoJ2knKX0gKiAke2Nvc0NhY2hlLmdldCgncG9zaXRpb25faWQnLCAnYnNuaFszXScpfSAtXG4gICAgICAgICAgICAgICAgJHtpbnB1dC5nZXRCeU9mZnNldCgnaicpfSAqICR7c2luQ2FjaGUuZ2V0KCdwb3NpdGlvbl9pZCcsICdic25oWzNdJyl9O1xuICAgICAgICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2knLCAncmUnKX1cbiAgICAgICAgICAgIGxldCBpbSA9ICR7aW5wdXQuZ2V0QnlPZmZzZXQoJ2knKX0gKiAke3NpbkNhY2hlLmdldCgncG9zaXRpb25faWQnLCAnYnNuaFszXScpfSArXG4gICAgICAgICAgICAgICAgJHtpbnB1dC5nZXRCeU9mZnNldCgnaicpfSAqICR7Y29zQ2FjaGUuZ2V0KCdwb3NpdGlvbl9pZCcsICdic25oWzNdJyl9O1xuICAgICAgICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2onLCAnaW0nKX1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGV0IGsgPSBkb3QoYnNuaCwgdW5pZm9ybXMuaW5wdXRfb3V0cHV0X3N0cmlkZXMpICsgaGFsZl9yb3RhcnlfZW1iX2RpbTtcbiAgICAgICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdrJywgaW5wdXQuZ2V0QnlPZmZzZXQoJ2snKSl9XG4gICAgICAgICAgfVxuICAgICAgICB9YDtcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdSb3RhcnlFbWJlZGRpbmcnLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe1xuICAgICAgICBpbnRlcmxlYXZlZCxcbiAgICAgIH0pLmNhY2hlS2V5LFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuaycsICdyYW5rJywgJ3JhbmsnLCAncmFuayddLFxuICAgIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBpbnB1dHNbMF0uZGltcywgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplKGdsb2JhbFNoYXBlKSAvIFdPUktHUk9VUF9TSVpFKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHJvdGFyeUVtYmVkZGluZyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogUm90YXJ5RW1iZWRkaW5nQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVSb3RhcnlFbWJlZGRpbmdQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcykpO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5cbmltcG9ydCB7IGFwcGx5QXR0ZW50aW9uLCBBdHRlbnRpb25NYXNrVHlwZSwgQXR0ZW50aW9uUGFyYW1ldGVycywgQXR0ZW50aW9uUWt2Rm9ybWF0IH0gZnJvbSAnLi9hdHRlbnRpb24nO1xuaW1wb3J0IHsgbWF5YmVUcmFuc3Bvc2VUb0JOU0hBbmRBZGRCaWFzIH0gZnJvbSAnLi9tdWx0aWhlYWQtYXR0ZW50aW9uJztcbmltcG9ydCB7IGNyZWF0ZVNwbGl0UHJvZ3JhbUluZm8sIFNwbGl0QXR0cmlidXRlcyB9IGZyb20gJy4vc3BsaXQnO1xuaW1wb3J0IHsgY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8sIFRyYW5zcG9zZUF0dHJpYnV0ZXMgfSBmcm9tICcuL3RyYW5zcG9zZSc7XG5pbXBvcnQgeyBSb3RhcnlFbWJlZGRpbmdBdHRyaWJ1dGVzLCBjcmVhdGVSb3RhcnlFbWJlZGRpbmdQcm9ncmFtSW5mbyB9IGZyb20gJy4vcm90YXJ5LWVtYmVkZGluZyc7XG5pbXBvcnQgeyBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyLCBVbmlmb3Jtc0FycmF5VHlwZSB9IGZyb20gJy4vY29tbW9uJztcbmV4cG9ydCBpbnRlcmZhY2UgR3JvdXBRdWVyeUF0dGVudGlvbkF0dHJpYnV0ZXMge1xuICBudW1IZWFkczogbnVtYmVyO1xuICBrdk51bUhlYWRzOiBudW1iZXI7XG4gIHNjYWxlOiBudW1iZXI7XG4gIHNvZnRjYXA6IG51bWJlcjtcbiAgZG9Sb3Rhcnk6IG51bWJlcjtcbiAgcm90YXJ5SW50ZXJsZWF2ZWQ6IG51bWJlcjtcbiAgc21vb3RoU29mdG1heDogYm9vbGVhbjtcbiAgbG9jYWxXaW5kb3dTaXplOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCB2YWxpZGF0ZUlucHV0cyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IEdyb3VwUXVlcnlBdHRlbnRpb25BdHRyaWJ1dGVzLFxuKTogQXR0ZW50aW9uUGFyYW1ldGVycyA9PiB7XG4gIGlmIChhdHRyaWJ1dGVzLmRvUm90YXJ5ICYmIGlucHV0cy5sZW5ndGggPD0gNykge1xuICAgIHRocm93IG5ldyBFcnJvcignY29zX2NhY2hlIGFuZCBzaW5fY2FjaGUgaW5wdXRzIGFyZSByZXF1aXJlZCBpZiBkb19yb3RhcnkgaXMgc3BlY2lmaWVkJyk7XG4gIH1cbiAgY29uc3QgcXVlcnkgPSBpbnB1dHNbMF07XG4gIGNvbnN0IGtleSA9IGlucHV0c1sxXTtcbiAgY29uc3QgdmFsdWUgPSBpbnB1dHNbMl07XG4gIGNvbnN0IHBhc3RLZXkgPSBpbnB1dHNbM107XG4gIGNvbnN0IHBhc3RWYWx1ZSA9IGlucHV0c1s0XTtcbiAgaWYgKGF0dHJpYnV0ZXMuZG9Sb3RhcnkgIT09IDAgJiYgaW5wdXRzLmxlbmd0aCA8PSA3KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb3NfY2FzdCBhbmQgc2luX2NhY2hlIGFyZSBleHBlY3RlZCBpZiBkb19yb3RhcnkgYXR0cmlidXRlIGlzIG5vbi16ZXJvJyk7XG4gIH1cbiAgaWYgKGF0dHJpYnV0ZXMubG9jYWxXaW5kb3dTaXplICE9PSAtMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignTG9jYWwgYXR0ZW50aW9uIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgfVxuICBpZiAoYXR0cmlidXRlcy5zb2Z0Y2FwICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdTb2Z0Y2FwIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgfVxuICBpZiAoYXR0cmlidXRlcy5yb3RhcnlJbnRlcmxlYXZlZCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignUm90YXJ5IGludGVybGVhdmVkIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgfVxuICBpZiAoYXR0cmlidXRlcy5zbW9vdGhTb2Z0bWF4KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdTbW9vdGggc29mdG1heCBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cbiAgLy8gQWJicmV2aWF0aW9uIGFuZCBNZWFuaW5nczpcbiAgLy8gICBCOiAgICBiYXRjaF9zaXplXG4gIC8vICAgUzogICAgc2VxdWVuY2VfbGVuZ3RoIChpbnB1dCBzZXF1ZW5jZSBsZW5ndGggb2YgcXVlcnkpXG4gIC8vICAgUDogICAgcGFzdF9zZXF1ZW5jZV9sZW5ndGggKHBhc3Qgc2VxdWVuY2UgbGVuZ3RoIG9mIGtleSBvciB2YWx1ZSlcbiAgLy8gICBMOiAgICBrdl9zZXF1ZW5jZV9sZW5ndGggKGlucHV0IHNlcXVlbmNlIGxlbmd0aCBvZiBrZXkgb3IgdmFsdWUpXG4gIC8vICAgTTogICAgbWF4X3NlcXVlbmNlX2xlbmd0aFxuICAvLyAgIFQ6ICAgIHRvdGFsX3NlcXVlbmNlX2xlbmd0aCA9IHBhc3Rfc2VxdWVuY2VfbGVuZ3RoICsga3Zfc2VxdWVuY2VfbGVuZ3RoXG4gIC8vICAgTjogICAgbnVtX2hlYWRzXG4gIC8vICAgSDogICAgaGVhZCBzaXplIGZvciBRIGFuZCBLLCBha2EgcV9oZWFkX3NpemUgb3Iga19oZWFkX3NpemUgb3IgcWtfaGVhZF9zaXplXG4gIC8vICAgSF92OiAgdl9oZWFkX3NpemVcbiAgLy8gICBEX2k6ICBpbnB1dCBoaWRkZW4gc2l6ZVxuICAvLyAgIEQ6ICAgIGhpZGRlbiBzaXplIGZvciBRIGFuZCBLIChEID0gTiAqIEgpLCBha2EgcV9oaWRkZW5fc2l6ZSBvciBrX2hpZGRlbl9zaXplIG9yIHFrX2hpZGRlbl9zaXplXG4gIC8vICAgRF92OiAgdl9oaWRkZW5fc2l6ZSA9IG51bV9oZWFkcyAqIHZfaGVhZF9zaXplXG5cbiAgLy8gICAgIHBhc3Rfa2V5ICAgICAgICAgICAgICAgICAgIDogKEIsIE4sIFMqLCBIKVxuICAvLyAgICAgcGFzdF92YWx1ZSAgICAgICAgICAgICAgICAgOiAoQiwgTiwgUyosIEgpXG4gIC8vIFdoZW4gbm8gcGFja2luZyBmb3IgcS9rL3Y6XG4gIC8vICAgICBxdWVyeSAgICAgICAgICAgIChRKSAgICAgICA6IChCLCBTLCBEKVxuICAvLyAgICAga2V5ICAgICAgICAgICAgICAoSykgICAgICAgOiAoQiwgTCwgRCkgb3IgKEIsIE4sIFMqLCBIKVxuICAvLyAgICAgdmFsdWUgICAgICAgICAgICAoVikgICAgICAgOiAoQiwgTCwgRF92KSBvciAoQiwgTiwgUyosIEgpXG4gIC8vIFdoZW4gcGFja2VkIGt2IGlzIHVzZWQ6XG4gIC8vICAgICBxdWVyeSAgICAgICAgICAgIChRKSAgICAgICA6IChCLCBTLCBEKVxuICAvLyAgICAga2V5ICAgICAgICAgICAgICAoSykgICAgICAgOiAoQiwgTCwgTiwgMiwgSClcbiAgLy8gICAgIHZhbHVlICAgICAgICAgICAgKFYpICAgICAgIDogTm9uZVxuICAvLyBXaGVuIHBhY2tlZCBxa3YgaXMgdXNlZDpcbiAgLy8gICAgIHF1ZXJ5ICAgICAgICAgICAgKFEpICAgICAgIDogKEIsIEwsIE4sIDMsIEgpIG9yIChCLCBTLCAzKkQpXG4gIC8vICAgICBrZXkgICAgICAgICAgICAgIChLKSAgICAgICA6IE5vbmVcbiAgLy8gICAgIHZhbHVlICAgICAgICAgICAgKFYpICAgICAgIDogTm9uZVxuXG4gIGlmIChxdWVyeS5kaW1zLmxlbmd0aCAhPT0gMyAmJiBxdWVyeS5kaW1zLmxlbmd0aCAhPT0gNSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgcXVlcnkgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAzIG9yIDUgZGltZW5zaW9ucycpO1xuICB9XG5cbiAgY29uc3QgZG1taGFQYWNraW5nID0gZmFsc2U7XG4gIGNvbnN0IGJhdGNoU2l6ZSA9IHF1ZXJ5LmRpbXNbMF07XG4gIGNvbnN0IHNlcXVlbmNlTGVuZ3RoID0gcXVlcnkuZGltc1sxXTtcbiAgbGV0IGhpZGRlblNpemUgPVxuICAgIHF1ZXJ5LmRpbXMubGVuZ3RoID09PSAzID8gKGRtbWhhUGFja2luZyA/IHF1ZXJ5LmRpbXNbMl0gLyAzIDogcXVlcnkuZGltc1syXSkgOiBhdHRyaWJ1dGVzLm51bUhlYWRzICogcXVlcnkuZGltc1s0XTtcbiAgbGV0IGt2U2VxdWVuY2VMZW5ndGggPSBzZXF1ZW5jZUxlbmd0aDtcblxuICBsZXQgcGFzdFNlcXVlbmNlTGVuZ3RoID0gMDtcbiAgY29uc3QgcGFja2VkUUtWID0gIWtleSB8fCBrZXkuZGltcy5sZW5ndGggPT09IDA7XG4gIGNvbnN0IGhlYWRTaXplID0gIXBhY2tlZFFLVlxuICAgID8gTWF0aC5mbG9vcihoaWRkZW5TaXplIC8gYXR0cmlidXRlcy5udW1IZWFkcylcbiAgICA6IE1hdGguZmxvb3IoaGlkZGVuU2l6ZSAvIChhdHRyaWJ1dGVzLm51bUhlYWRzICsgMiAqIGF0dHJpYnV0ZXMua3ZOdW1IZWFkcykpO1xuICBpZiAocGFja2VkUUtWKSB7XG4gICAgaGlkZGVuU2l6ZSA9IGhlYWRTaXplICogYXR0cmlidXRlcy5udW1IZWFkcztcbiAgfVxuICBjb25zdCBoYXNQYXN0S2V5ID0gcGFzdEtleSAmJiBwYXN0S2V5LmRpbXMubGVuZ3RoICE9PSAwO1xuICBjb25zdCBoYXNQYXN0VmFsdWUgPSBwYXN0VmFsdWUgJiYgcGFzdFZhbHVlLmRpbXMubGVuZ3RoICE9PSAwO1xuICAvLyBDdXJyZW5seSB0aGUgb25ueHJ1bnRpbWUgR1FBIHNwZWNpZmljYXRpb24gb25seSBzdXBwb3J0IGtleS92YWx1ZSBCTlNIIGZvcm1hdC5cbiAgY29uc3QgaXNQYXN0a3ZCU05IID1cbiAgICBoYXNQYXN0S2V5ICYmXG4gICAgcGFzdEtleS5kaW1zLmxlbmd0aCA9PT0gNCAmJlxuICAgIHBhc3RLZXkuZGltc1swXSA9PT0gYmF0Y2hTaXplICYmXG4gICAgcGFzdEtleS5kaW1zWzFdICE9PSBhdHRyaWJ1dGVzLmt2TnVtSGVhZHMgJiZcbiAgICBwYXN0S2V5LmRpbXNbMl0gPT09IGF0dHJpYnV0ZXMua3ZOdW1IZWFkcyAmJlxuICAgIHBhc3RLZXkuZGltc1szXSA9PT0gaGVhZFNpemU7XG5cbiAgaWYgKGlzUGFzdGt2QlNOSCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQlNOSCBwYXN0S2V5L3Bhc3RWYWx1ZSBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cbiAgaWYgKGhhc1Bhc3RLZXkgJiYgaGFzUGFzdFZhbHVlKSB7XG4gICAgaWYgKHBhc3RLZXkuZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0X2tleVwiIGlzIGV4cGVjdGVkIHRvIGhhdmUgNCBkaW1lbnNpb25zJyk7XG4gICAgfVxuICAgIGlmIChwYXN0VmFsdWUuZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJwYXN0X3ZhbHVlXCIgaXMgZXhwZWN0ZWQgdG8gaGF2ZSA0IGRpbWVuc2lvbnMnKTtcbiAgICB9XG4gICAgcGFzdFNlcXVlbmNlTGVuZ3RoID0gcGFzdEtleS5kaW1zWzJdO1xuICB9IGVsc2UgaWYgKGhhc1Bhc3RLZXkgfHwgaGFzUGFzdFZhbHVlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInBhc3Rfa2V5XCIgYW5kIFwicGFzdF92YWx1ZVwiIHNoYWxsIGJlIGJvdGggcHJlc2VudCBvciBib3RoIGFic2VudCcpO1xuICB9XG5cbiAgbGV0IHFrdkZvcm1hdDogQXR0ZW50aW9uUWt2Rm9ybWF0ID0gQXR0ZW50aW9uUWt2Rm9ybWF0LnFrdkJOU0g7XG4gIGlmIChrZXkgJiYga2V5LmRpbXMubGVuZ3RoID4gMCkge1xuICAgIGlmIChxdWVyeS5kaW1zLmxlbmd0aCAhPT0gMykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInF1ZXJ5XCIgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAzIGRpbWVuc2lvbnMgd2hlbiBrZXkgaXMgZ2l2ZW4nKTtcbiAgICB9XG4gICAgaWYgKGtleS5kaW1zLmxlbmd0aCA8IDMgfHwga2V5LmRpbXMubGVuZ3RoID4gNSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcImtleVwiIGlzIGV4cGVjdGVkIHRvIGhhdmUgMywgNCwgb3IgNSBkaW1lbnNpb25zJyk7XG4gICAgfVxuICAgIGlmIChxdWVyeS5kaW1zWzBdICE9PSBrZXkuZGltc1swXSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInF1ZXJ5XCIgYW5kIFwia2V5XCIgc2hhbGwgaGF2ZSBzYW1lIGRpbSAwIChiYXRjaCBzaXplKScpO1xuICAgIH1cblxuICAgIGlmIChrZXkuZGltcy5sZW5ndGggPT09IDMpIHtcbiAgICAgIGlmIChxdWVyeS5kaW1zWzJdICUga2V5LmRpbXNbMl0gIT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEaW1lbnNpb24gMiBvZiBcInF1ZXJ5XCIgc2hvdWxkIGJlIGEgbXVsdGlwbGUgb2YgXCJrZXlcIicpO1xuICAgICAgfVxuICAgICAga3ZTZXF1ZW5jZUxlbmd0aCA9IGtleS5kaW1zWzFdO1xuICAgIH0gZWxzZSBpZiAoa2V5LmRpbXMubGVuZ3RoID09PSA1KSB7XG4gICAgICBpZiAoa2V5LmRpbXNbMl0gIT09IGF0dHJpYnV0ZXMubnVtSGVhZHMgfHwga2V5LmRpbXNbM10gIT09IDIgfHwga2V5LmRpbXNbNF0gIT09IGhlYWRTaXplKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0IFwia2V5XCIgc2hhcGUgKGJhdGNoX3NpemUsIGt2X3NlcXVlbmNlX2xlbmd0aCwgbnVtX2hlYWRzLCAyLCBoZWFkX3NpemUpIGZvciBwYWNrZWQga3YnKTtcbiAgICAgIH1cbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdCBcInZhbHVlXCIgYmUgbm9uZSB3aGVuIFwia2V5XCIgaGFzIHBhY2tlZCBrdiBmb3JtYXQuJyk7XG4gICAgICB9XG4gICAgICBrdlNlcXVlbmNlTGVuZ3RoID0ga2V5LmRpbXNbMV07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGtleV9kaW1zLnNpemUoKSA9PSA0IChjcm9zcy1hdHRlbnRpb24gd2l0aCBwYXN0X2tleSlcbiAgICAgIGlmIChrZXkuZGltc1sxXSAhPT0gYXR0cmlidXRlcy5udW1IZWFkcyB8fCBrZXkuZGltc1szXSAhPT0gaGVhZFNpemUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3QgXCJrZXlcIiBzaGFwZSAoYmF0Y2hfc2l6ZSwgbnVtX2hlYWRzLCBrdl9zZXF1ZW5jZV9sZW5ndGgsIGhlYWRfc2l6ZSkgZm9yIHBhc3Rfa2V5Jyk7XG4gICAgICB9XG4gICAgICBrdlNlcXVlbmNlTGVuZ3RoID0ga2V5LmRpbXNbMl07XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIHBhY2tlZCBRS1ZcbiAgICBpZiAocXVlcnkuZGltcy5sZW5ndGggIT09IDMgJiYgcXVlcnkuZGltcy5sZW5ndGggIT09IDUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJxdWVyeVwiIGlzIGV4cGVjdGVkIHRvIGhhdmUgMyBvciA1IGRpbWVuc2lvbnMgd2hlbiBrZXkgaXMgZW1wdHknKTtcbiAgICB9XG4gICAgaWYgKHF1ZXJ5LmRpbXMubGVuZ3RoID09PSA1ICYmIChxdWVyeS5kaW1zWzJdICE9PSBhdHRyaWJ1dGVzLm51bUhlYWRzIHx8IHF1ZXJ5LmRpbXNbM10gIT09IDMpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdCBcInF1ZXJ5XCIgc2hhcGUgKGJhdGNoX3NpemUsIGt2X3NlcXVlbmNlX2xlbmd0aCwgbnVtX2hlYWRzLCAzLCBoZWFkX3NpemUpIGZvciBwYWNrZWQga3YnKTtcbiAgICB9XG5cbiAgICBxa3ZGb3JtYXQgPSBBdHRlbnRpb25Ra3ZGb3JtYXQucWt2QlNOM0g7XG4gIH1cblxuICBjb25zdCBtYXNrVHlwZTogQXR0ZW50aW9uTWFza1R5cGUgPSBBdHRlbnRpb25NYXNrVHlwZS5ub25lO1xuICBsZXQgcGFzc1Bhc3RJbkt2ID0gZmFsc2U7XG4gIGxldCB2SGlkZGVuU2l6ZSA9IGF0dHJpYnV0ZXMua3ZOdW1IZWFkcyA/IGhlYWRTaXplICogYXR0cmlidXRlcy5rdk51bUhlYWRzIDogaGlkZGVuU2l6ZTtcbiAgaWYgKHZhbHVlICYmIHZhbHVlLmRpbXMubGVuZ3RoID4gMCkge1xuICAgIGlmICh2YWx1ZS5kaW1zLmxlbmd0aCAhPT0gMyAmJiB2YWx1ZS5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInZhbHVlXCIgaXMgZXhwZWN0ZWQgdG8gaGF2ZSAzIG9yIDQgZGltZW5zaW9ucycpO1xuICAgIH1cblxuICAgIGlmIChxdWVyeS5kaW1zWzBdICE9PSB2YWx1ZS5kaW1zWzBdKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IFwicXVlcnlcIiBhbmQgXCJ2YWx1ZVwiIHNoYWxsIGhhdmUgc2FtZSBkaW0gMCAoYmF0Y2hfc2l6ZSknKTtcbiAgICB9XG5cbiAgICBpZiAodmFsdWUuZGltcy5sZW5ndGggPT09IDMpIHtcbiAgICAgIGlmIChrdlNlcXVlbmNlTGVuZ3RoICE9PSB2YWx1ZS5kaW1zWzFdKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgXCJrZXlcIiBhbmQgXCJ2YWx1ZVwiIHNoYWxsIGhhdmUgdGhlIHNhbWUgZGltIDEgKGt2X3NlcXVlbmNlX2xlbmd0aCknKTtcbiAgICAgIH1cbiAgICAgIHZIaWRkZW5TaXplID0gdmFsdWUuZGltc1syXTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGt2U2VxdWVuY2VMZW5ndGggIT09IHZhbHVlLmRpbXNbMl0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInBhc3Rfa2V5XCIgYW5kIFwicGFzdF92YWx1ZVwiIHNoYWxsIGhhdmUgdGhlIHNhbWUgZGltIDIgKGt2X3NlcXVlbmNlX2xlbmd0aCknKTtcbiAgICAgIH1cbiAgICAgIHZIaWRkZW5TaXplID0gdmFsdWUuZGltc1sxXSAqIHZhbHVlLmRpbXNbM107XG4gICAgICBwYXNzUGFzdEluS3YgPSB0cnVlO1xuICAgIH1cbiAgfVxuICBjb25zdCBzZXFsTGVucyA9IGlucHV0cy5sZW5ndGggPiA0ID8gaW5wdXRzWzVdIDogdW5kZWZpbmVkO1xuICBpZiAoc2VxbExlbnMgJiYgc2VxbExlbnMuZGltcy5sZW5ndGggIT09IDEgJiYgc2VxbExlbnMuZGltc1swXSAhPT0gYmF0Y2hTaXplKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBcInNlcWxlbnNcIiBpcyBleHBlY3RlZCB0byBoYXZlIDEgZGltZW5zaW9uIGFuZCB0aGUgc2FtZSBkaW0gMCBhcyBiYXRjaF9zaXplJyk7XG4gIH1cbiAgY29uc3QgdG90YWxTZXF1ZW5jZUxlbmd0aCA9IC0xO1xuICBjb25zdCBtYXhTZXF1ZW5jZUxlbmd0aCA9IC0xO1xuICBjb25zdCBicm9hZGNhc3RSZXNQb3NCaWFzID0gZmFsc2U7XG5cbiAgcmV0dXJuIHtcbiAgICBiYXRjaFNpemUsXG4gICAgc2VxdWVuY2VMZW5ndGgsXG4gICAgcGFzdFNlcXVlbmNlTGVuZ3RoLFxuICAgIGt2U2VxdWVuY2VMZW5ndGgsXG4gICAgdG90YWxTZXF1ZW5jZUxlbmd0aCxcbiAgICBtYXhTZXF1ZW5jZUxlbmd0aCxcbiAgICBpbnB1dEhpZGRlblNpemU6IDAsXG4gICAgaGlkZGVuU2l6ZSxcbiAgICB2SGlkZGVuU2l6ZSxcbiAgICBoZWFkU2l6ZSxcbiAgICB2SGVhZFNpemU6IE1hdGguZmxvb3IodkhpZGRlblNpemUgLyBhdHRyaWJ1dGVzLmt2TnVtSGVhZHMpLFxuICAgIG51bUhlYWRzOiBhdHRyaWJ1dGVzLm51bUhlYWRzLFxuICAgIGt2TnVtSGVhZHM6IGF0dHJpYnV0ZXMua3ZOdW1IZWFkcyxcbiAgICBuUmVwczogYXR0cmlidXRlcy5udW1IZWFkcyAvIGF0dHJpYnV0ZXMua3ZOdW1IZWFkcyxcbiAgICBwYXN0UHJlc2VudFNoYXJlQnVmZmVyOiBmYWxzZSxcbiAgICBtYXNrVHlwZSxcbiAgICBzY2FsZTogYXR0cmlidXRlcy5zY2FsZSxcbiAgICBicm9hZGNhc3RSZXNQb3NCaWFzLFxuICAgIHBhc3NQYXN0SW5LdixcbiAgICBxa3ZGb3JtYXQsXG4gIH07XG59O1xuXG5jb25zdCB3ZWlnaHRUcmFuc3Bvc2VBdHRyaWJ1dGU6IFRyYW5zcG9zZUF0dHJpYnV0ZXMgPSBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyBwZXJtOiBbMCwgMiwgMSwgM10gfSk7XG5cbmNvbnN0IG1heWJlVHJhbnNwb3NlVG9CTlNIID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBpbnB1dDogVGVuc29yVmlldywgcGFyYW1zOiBBdHRlbnRpb25QYXJhbWV0ZXJzKSA9PiB7XG4gIGxldCByZXNoYXBlZElucHV0ID0gaW5wdXQ7XG4gIGNvbnN0IG51bUhlYWRzID0gcGFyYW1zLmt2TnVtSGVhZHMhO1xuICBpZiAoaW5wdXQuZGltcy5sZW5ndGggPT09IDMgJiYgcGFyYW1zLmt2U2VxdWVuY2VMZW5ndGggIT09IDApIHtcbiAgICByZXNoYXBlZElucHV0ID0gaW5wdXQucmVzaGFwZShbcGFyYW1zLmJhdGNoU2l6ZSwgcGFyYW1zLmt2U2VxdWVuY2VMZW5ndGgsIG51bUhlYWRzLCBwYXJhbXMuaGVhZFNpemVdKTtcbiAgICByZXNoYXBlZElucHV0ID0gY29udGV4dC5jb21wdXRlKGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvKHJlc2hhcGVkSW5wdXQsIHdlaWdodFRyYW5zcG9zZUF0dHJpYnV0ZS5wZXJtKSwge1xuICAgICAgaW5wdXRzOiBbcmVzaGFwZWRJbnB1dF0sXG4gICAgICBvdXRwdXRzOiBbLTFdLFxuICAgIH0pWzBdO1xuICB9XG5cbiAgcmV0dXJuIHJlc2hhcGVkSW5wdXQ7XG59O1xuXG5jb25zdCBnZW5lcmF0ZVBvc2l0aW9uSWRzUHJvZ3JhbUluZm8gPSAoXG4gIGJhdGNoU2l6ZTogbnVtYmVyLFxuICBzZXF1ZW5jZUxlbmd0aDogbnVtYmVyLFxuICBzZXFMZW5zOiBUZW5zb3JWaWV3LFxuICB0b3RhbFNlcUxlbjogVGVuc29yVmlldyxcbikgPT4ge1xuICBjb25zdCBvdXRwdXREYXRhVHlwZSA9IERhdGFUeXBlLmludDY0O1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsndHlwZScsICd0eXBlJ107XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gW2JhdGNoU2l6ZSAqIHNlcXVlbmNlTGVuZ3RoXTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IGJhdGNoU2l6ZSAqIHNlcXVlbmNlTGVuZ3RoO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogc2VxdWVuY2VMZW5ndGggfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYmF0Y2hTaXplIH0sXG4gIF07XG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IHNlcUxlbnNJbnB1dEhlbHBlciA9IGlucHV0VmFyaWFibGUoJ3NlcV9sZW5zJywgc2VxTGVucy5kYXRhVHlwZSwgc2VxTGVucy5kaW1zKTtcbiAgICBjb25zdCB0b3RhbFNlcUxlbklucHV0SGVscGVyID0gaW5wdXRWYXJpYWJsZSgndG90YWxfc2VxX2xlbnMnLCB0b3RhbFNlcUxlbi5kYXRhVHlwZSwgdG90YWxTZXFMZW4uZGltcyk7XG4gICAgY29uc3QgcG9zaXRpb25JZHNIZWxwZXIgPSBvdXRwdXRWYXJpYWJsZSgncG9zX2lkcycsIG91dHB1dERhdGFUeXBlLCBvdXRwdXRTaGFwZSk7XG5cbiAgICBjb25zdCB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUgPSBbXG4gICAgICB7IG5hbWU6ICdvdXRwdXRfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgICB7IG5hbWU6ICdzZXF1ZW5jZV9sZW5ndGgnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnYmF0Y2hfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcblxuICAgIHJldHVybiBgXG4gICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMoc2VxTGVuc0lucHV0SGVscGVyLCB0b3RhbFNlcUxlbklucHV0SGVscGVyLCBwb3NpdGlvbklkc0hlbHBlcil9XG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgbGV0IHRvdGFsX3NlcXVlbmNlX2xlbmd0aCA9IHUzMigke3RvdGFsU2VxTGVuSW5wdXRIZWxwZXIuZ2V0QnlPZmZzZXQoJzAnKX0pO1xuICAgIGxldCBpc19zdWJzZXF1ZW50X3Byb21wdCA9IHVuaWZvcm1zLnNlcXVlbmNlX2xlbmd0aCA+IDEgJiYgdW5pZm9ybXMuc2VxdWVuY2VfbGVuZ3RoICE9IHRvdGFsX3NlcXVlbmNlX2xlbmd0aDtcbiAgICBsZXQgaXNfZmlyc3RfcHJvbXB0ID0gIWlzX3N1YnNlcXVlbnRfcHJvbXB0ICYmIHVuaWZvcm1zLnNlcXVlbmNlX2xlbmd0aCA9PSB0b3RhbF9zZXF1ZW5jZV9sZW5ndGg7XG4gICAgbGV0IGJhdGNoX2lkeCA9IGdsb2JhbF9pZHggLyB1bmlmb3Jtcy5zZXF1ZW5jZV9sZW5ndGg7XG4gICAgbGV0IHNlcXVlbmNlX2lkeCA9IGkzMihnbG9iYWxfaWR4ICUgdW5pZm9ybXMuc2VxdWVuY2VfbGVuZ3RoKTtcbiAgICB2YXIgcG9zX2lkOiBpMzIgPSAwO1xuICAgIGxldCBzZXFsZW4gPSAke3NlcUxlbnNJbnB1dEhlbHBlci5nZXRCeU9mZnNldCgnYmF0Y2hfaWR4Jyl9O1xuICAgIGxldCB0b3RhbF9zZXFsZW4gPSBzZXFsZW4gKyAxO1xuICAgIGlmIChpc19maXJzdF9wcm9tcHQpIHtcbiAgICAgIGlmIChzZXF1ZW5jZV9pZHggPCB0b3RhbF9zZXFsZW4pIHtcbiAgICAgICAgcG9zX2lkID0gc2VxdWVuY2VfaWR4O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcG9zX2lkID0gMTtcbiAgICAgIH1cbiAgICAgICR7cG9zaXRpb25JZHNIZWxwZXIuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAncG9zX2lkJyl9XG4gICAgfSBlbHNlIGlmIChpc19zdWJzZXF1ZW50X3Byb21wdCkge1xuICAgICAgbGV0IHBhc3Rfc2VxbGVuID0gdG90YWxfc2VxbGVuIC0gaTMyKHVuaWZvcm1zLnNlcXVlbmNlX2xlbmd0aCk7XG4gICAgICBpZiAocGFzdF9zZXFsZW4gKyBzZXF1ZW5jZV9pZHggPCB0b3RhbF9zZXFsZW4pIHtcbiAgICAgICAgcG9zX2lkID0gcGFzdF9zZXFsZW4gKyBzZXF1ZW5jZV9pZHg7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwb3NfaWQgPSAxO1xuICAgICAgfVxuICAgICAgJHtwb3NpdGlvbklkc0hlbHBlci5zZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcsICdwb3NfaWQnKX1cbiAgICB9IGVsc2UgaWYgKGdsb2JhbF9pZHggPCB1bmlmb3Jtcy5iYXRjaF9zaXplKSB7XG4gICAgICAke3Bvc2l0aW9uSWRzSGVscGVyLnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgJ3NlcWxlbicpfVxuICAgIH07XG4gIH1cbiAgYDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnR2VuZXJhdGVQb3NpdGlvbklkcycsXG4gICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7YmF0Y2hTaXplfTske3NlcXVlbmNlTGVuZ3RofWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogb3V0cHV0RGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGdyb3VwUXVlcnlBdHRlbnRpb24gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEdyb3VwUXVlcnlBdHRlbnRpb25BdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IHBhcmFtcyA9IHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgaWYgKGNvbnRleHQuaW5wdXRzWzBdLmRpbXMubGVuZ3RoID09PSA1KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQYWNrZWQgUUtWIGlzIG5vdCBpbXBsZW1lbnRlZCcpO1xuICB9XG5cbiAgaWYgKGNvbnRleHQuaW5wdXRzWzFdPy5kaW1zLmxlbmd0aCA9PT0gNSkge1xuICAgIHRocm93IG5ldyBFcnJvcignUGFja2VkIEtWIGlzIG5vdCBpbXBsZW1lbnRlZCcpO1xuICB9XG5cbiAgY29uc3QgcSA9IGNvbnRleHQuaW5wdXRzWzBdO1xuICBjb25zdCBrID0gY29udGV4dC5pbnB1dHNbMV0gJiYgY29udGV4dC5pbnB1dHNbMV0uZGltcy5sZW5ndGggPiAwID8gY29udGV4dC5pbnB1dHNbMV0gOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHYgPSBjb250ZXh0LmlucHV0c1syXSAmJiBjb250ZXh0LmlucHV0c1syXS5kaW1zLmxlbmd0aCA+IDAgPyBjb250ZXh0LmlucHV0c1syXSA6IHVuZGVmaW5lZDtcbiAgY29uc3QgcGFzdEtleSA9IGNvbnRleHQuaW5wdXRzWzNdICYmIGNvbnRleHQuaW5wdXRzWzNdLmRpbXMubGVuZ3RoICE9PSAwID8gY29udGV4dC5pbnB1dHNbM10gOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHBhc3RWYWx1ZSA9IGNvbnRleHQuaW5wdXRzWzRdICYmIGNvbnRleHQuaW5wdXRzWzRdLmRpbXMubGVuZ3RoICE9PSAwID8gY29udGV4dC5pbnB1dHNbNF0gOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHNlcUxlbnMgPSBjb250ZXh0LmlucHV0cy5sZW5ndGggPiA0ID8gY29udGV4dC5pbnB1dHNbNV0gOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCA9IGNvbnRleHQuaW5wdXRzLmxlbmd0aCA+IDUgPyBjb250ZXh0LmlucHV0c1s2XSA6IHVuZGVmaW5lZDtcbiAgY29uc3Qga3ZOdW1IZWFkcyA9IHBhcmFtcy5rdk51bUhlYWRzID8gcGFyYW1zLmt2TnVtSGVhZHMgOiBwYXJhbXMubnVtSGVhZHM7XG5cbiAgLy8gVE9ETyBSZW1vdmUgZXhwbGljaXQgc3BsaXQgb3BlcmF0aW9uIGFuZCB1c2UgaW5kZXhpbmcgaW4gQXR0ZW50aW9uIGltcGxlbWVudGF0aW9uIHRvIGF2b2lkIG92ZXJoZWFkLlxuXG4gIGNvbnN0IHNwbGl0QXR0cmlidXRlczogU3BsaXRBdHRyaWJ1dGVzID0gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtcbiAgICBheGlzOiAyLFxuICAgIG51bU91dHB1dHM6IDMsXG4gICAgc3BsaXRTaXplczogW3BhcmFtcy5udW1IZWFkcyAqIHBhcmFtcy5oZWFkU2l6ZSwga3ZOdW1IZWFkcyAqIHBhcmFtcy5oZWFkU2l6ZSwga3ZOdW1IZWFkcyAqIHBhcmFtcy5oZWFkU2l6ZV0sXG4gIH0pO1xuICBjb25zdCBbcXVlcnksIGtleSwgdmFsdWVdID1cbiAgICAhayAmJiAhdlxuICAgICAgPyBjb250ZXh0LmNvbXB1dGUoY3JlYXRlU3BsaXRQcm9ncmFtSW5mbyhbcV0sIHNwbGl0QXR0cmlidXRlcyksIHsgaW5wdXRzOiBbcV0sIG91dHB1dHM6IFstMSwgLTEsIC0xXSB9KVxuICAgICAgOiBbcSwgayEsIHYhXTtcbiAgbGV0IHFSb3Rhcnk6IFRlbnNvclZpZXcgfCB1bmRlZmluZWQ7XG4gIGxldCBrUm90YXJ5OiBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkO1xuICBpZiAoYXR0cmlidXRlcy5kb1JvdGFyeSkge1xuICAgIGNvbnN0IHBvc0lkcyA9IGNvbnRleHQuY29tcHV0ZShcbiAgICAgIGdlbmVyYXRlUG9zaXRpb25JZHNQcm9ncmFtSW5mbyhwYXJhbXMuYmF0Y2hTaXplLCBwYXJhbXMuc2VxdWVuY2VMZW5ndGgsIHNlcUxlbnMhLCB0b3RhbFNlcXVlbmNlTGVuZ3RoSW5wdXQhKSxcbiAgICAgIHsgaW5wdXRzOiBbc2VxTGVucyEsIHRvdGFsU2VxdWVuY2VMZW5ndGhJbnB1dCFdLCBvdXRwdXRzOiBbLTFdIH0sXG4gICAgKVswXTtcbiAgICBjb25zdCBjb3NDYWNoZSA9IGNvbnRleHQuaW5wdXRzWzddO1xuICAgIGNvbnN0IHNpbkNhY2hlID0gY29udGV4dC5pbnB1dHNbOF07XG4gICAgY29uc3QgcVJvdGFyeUVtYmVkZGluZ0F0dHJpYnV0ZXM6IFJvdGFyeUVtYmVkZGluZ0F0dHJpYnV0ZXMgPSBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe1xuICAgICAgaW50ZXJsZWF2ZWQ6IGF0dHJpYnV0ZXMucm90YXJ5SW50ZXJsZWF2ZWQgIT09IDAsXG4gICAgICBudW1IZWFkczogcGFyYW1zLm51bUhlYWRzLFxuICAgICAgcm90YXJ5RW1iZWRkaW5nRGltOiAwLFxuICAgICAgc2NhbGU6IGF0dHJpYnV0ZXMuc2NhbGUsXG4gICAgfSk7XG4gICAgY29uc3QgaW5wdXRzID0gW3F1ZXJ5LCBwb3NJZHMsIGNvc0NhY2hlLCBzaW5DYWNoZV07XG4gICAgY29uc3Qgb3V0cHV0cyA9IFstMV07XG4gICAgcVJvdGFyeSA9IGNvbnRleHQuY29tcHV0ZShjcmVhdGVSb3RhcnlFbWJlZGRpbmdQcm9ncmFtSW5mbyhpbnB1dHMsIHFSb3RhcnlFbWJlZGRpbmdBdHRyaWJ1dGVzKSwge1xuICAgICAgaW5wdXRzLFxuICAgICAgb3V0cHV0cyxcbiAgICB9KVswXTtcbiAgICBpbnB1dHMuc3BsaWNlKDAsIDEsIGtleSk7XG4gICAgY29uc3Qga1JvdGFyeUVtYmVkZGluZ0F0dHJpYnV0ZXM6IFJvdGFyeUVtYmVkZGluZ0F0dHJpYnV0ZXMgPSBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe1xuICAgICAgaW50ZXJsZWF2ZWQ6IGF0dHJpYnV0ZXMucm90YXJ5SW50ZXJsZWF2ZWQgIT09IDAsXG4gICAgICBudW1IZWFkczogcGFyYW1zLmt2TnVtSGVhZHMhLFxuICAgICAgcm90YXJ5RW1iZWRkaW5nRGltOiAwLFxuICAgICAgc2NhbGU6IGF0dHJpYnV0ZXMuc2NhbGUsXG4gICAgfSk7XG4gICAga1JvdGFyeSA9IGNvbnRleHQuY29tcHV0ZShjcmVhdGVSb3RhcnlFbWJlZGRpbmdQcm9ncmFtSW5mbyhpbnB1dHMsIGtSb3RhcnlFbWJlZGRpbmdBdHRyaWJ1dGVzKSwge1xuICAgICAgaW5wdXRzLFxuICAgICAgb3V0cHV0cyxcbiAgICB9KVswXTtcbiAgfVxuICBjb25zdCBRID0gbWF5YmVUcmFuc3Bvc2VUb0JOU0hBbmRBZGRCaWFzKFxuICAgIGNvbnRleHQsXG4gICAgcGFyYW1zLmJhdGNoU2l6ZSxcbiAgICBwYXJhbXMubnVtSGVhZHMsXG4gICAgcGFyYW1zLnNlcXVlbmNlTGVuZ3RoLFxuICAgIHBhcmFtcy5oZWFkU2l6ZSxcbiAgICBhdHRyaWJ1dGVzLmRvUm90YXJ5ID8gcVJvdGFyeSEgOiBxdWVyeSxcbiAgICB1bmRlZmluZWQsXG4gICAgMCxcbiAgKTtcbiAgY29uc3QgSyA9IG1heWJlVHJhbnNwb3NlVG9CTlNIKGNvbnRleHQsIGF0dHJpYnV0ZXMuZG9Sb3RhcnkgPyBrUm90YXJ5ISA6IGtleSwgcGFyYW1zKTtcbiAgY29uc3QgViA9IG1heWJlVHJhbnNwb3NlVG9CTlNIKGNvbnRleHQsIHZhbHVlLCBwYXJhbXMpO1xuXG4gIGFwcGx5QXR0ZW50aW9uKFxuICAgIGNvbnRleHQsXG4gICAgUSxcbiAgICBLLFxuICAgIFYsXG4gICAgdW5kZWZpbmVkLFxuICAgIHVuZGVmaW5lZCxcbiAgICBwYXN0S2V5LFxuICAgIHBhc3RWYWx1ZSxcbiAgICB1bmRlZmluZWQsXG4gICAgcGFyYW1zLFxuICAgIHNlcUxlbnMsXG4gICAgdG90YWxTZXF1ZW5jZUxlbmd0aElucHV0LFxuICApO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHsgY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8gfSBmcm9tICcuL3RyYW5zcG9zZSc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBnZXRNYXhDb21wb25lbnRzLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICBzdW1WZWN0b3IsXG4gIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSxcbn0gZnJvbSAnLi9jb21tb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIEluc3RhbmNlTm9ybUF0dHJpYnV0ZXMge1xuICBlcHNpbG9uOiBudW1iZXI7XG4gIGZvcm1hdDogJ05IV0MnIHwgJ05DSFcnO1xufVxuXG5jb25zdCBjb21wdXRlQ2hhbm5lbFNjYWxlU2hpZnQgPSAoXG4gIGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LFxuICBpbnB1dDogVGVuc29yVmlldyxcbiAgc2NhbGU6IFRlbnNvclZpZXcsXG4gIGJpYXM6IFRlbnNvclZpZXcsXG4gIG46IG51bWJlcixcbiAgaDogbnVtYmVyLFxuICBjOiBudW1iZXIsXG4gIGVwc2lsb246IG51bWJlcixcbikgPT4ge1xuICBjb25zdCBjb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhoKTtcbiAgY29uc3QgZjMyVHlwZSA9IGNvbXBvbmVudHMgPT09IDEgPyAnZjMyJyA6IGB2ZWMke2NvbXBvbmVudHN9ZmA7XG4gIGNvbnN0IHdnVHlwZSA9IGNvbXBvbmVudHMgPT09IDEgPyAndmVjMmYnIDogYG1hdDJ4JHtjb21wb25lbnRzfWZgO1xuICBjb25zdCB1bml0c09mV29yayA9IG4gKiBjO1xuICBsZXQgd29ya2dyb3VwU2l6ZSA9IDY0O1xuICBpZiAodW5pdHNPZldvcmsgPT09IDEpIHtcbiAgICB3b3JrZ3JvdXBTaXplID0gMjU2O1xuICB9XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBbbiwgYywgaCAvIGNvbXBvbmVudHNdO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IFtuLCBjLCAyXTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3JhbmsnLCAndHlwZScsICd0eXBlJ107XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtdO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dFNoYXBlLCBvdXRwdXRTaGFwZSkpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IHggPSBpbnB1dFZhcmlhYmxlKCd4JywgaW5wdXQuZGF0YVR5cGUsIDMsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IHMgPSBpbnB1dFZhcmlhYmxlKCdzY2FsZScsIHNjYWxlLmRhdGFUeXBlLCBzY2FsZS5kaW1zKTtcbiAgICBjb25zdCBiID0gaW5wdXRWYXJpYWJsZSgnYmlhcycsIGJpYXMuZGF0YVR5cGUsIGJpYXMuZGltcyk7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIERhdGFUeXBlLmZsb2F0LCAzLCAyKTtcbiAgICBjb25zdCB2YXJpYWJsZXMgPSBbeCwgcywgYiwgb3V0cHV0XTtcbiAgICByZXR1cm4gYFxuICB2YXI8d29ya2dyb3VwPiB3b3JrZ3JvdXBfc2hhcmVkIDogYXJyYXk8JHt3Z1R5cGV9LCAke3dvcmtncm91cFNpemV9PjtcbiAgY29uc3Qgd29ya2dyb3VwX3NpemUgPSAke3dvcmtncm91cFNpemV9dTtcbiAgJHtzaGFkZXJIZWxwZXIuZGVjbGFyZVZhcmlhYmxlcyguLi52YXJpYWJsZXMpfVxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQod29ya2dyb3VwU2l6ZSl9XG4gICAgbGV0IGJhdGNoID0gd29ya2dyb3VwX2luZGV4IC8gdW5pZm9ybXMueF9zaGFwZVsxXTtcbiAgICBsZXQgY2hhbm5lbCA9IHdvcmtncm91cF9pbmRleCAlIHVuaWZvcm1zLnhfc2hhcGVbMV07XG4gICAgbGV0IGhpZ2h0ID0gdW5pZm9ybXMueF9zaGFwZVsyXTtcbiAgICAvLyBpbml0aWFsaXplIHdvcmtncm91cCBtZW1vcnlcbiAgICB2YXIgc3VtID0gJHtmMzJUeXBlfSgwKTtcbiAgICB2YXIgc3F1YXJlZF9zdW0gPSAke2YzMlR5cGV9KDApO1xuICAgIGZvciAodmFyIGggPSBsb2NhbF9pZHg7IGggPCBoaWdodDsgaCArPSB3b3JrZ3JvdXBfc2l6ZSkge1xuICAgICAgbGV0IHZhbHVlID0gJHtmMzJUeXBlfSgke3guZ2V0KCdiYXRjaCcsICdjaGFubmVsJywgJ2gnKX0pO1xuICAgICAgc3VtICs9IHZhbHVlO1xuICAgICAgc3F1YXJlZF9zdW0gKz0gdmFsdWUgKiB2YWx1ZTtcbiAgICB9XG4gICAgd29ya2dyb3VwX3NoYXJlZFtsb2NhbF9pZHhdID0gJHt3Z1R5cGV9KHN1bSwgc3F1YXJlZF9zdW0pO1xuICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgIGZvciAodmFyIGN1cnJTaXplID0gd29ya2dyb3VwX3NpemUgPj4gMTsgIGN1cnJTaXplID4gMDsgY3VyclNpemUgPSBjdXJyU2l6ZSA+PiAxKSB7XG4gICAgICBpZiAobG9jYWxfaWR4IDwgY3VyclNpemUpIHtcbiAgICAgICAgd29ya2dyb3VwX3NoYXJlZFtsb2NhbF9pZHhdID0gd29ya2dyb3VwX3NoYXJlZFtsb2NhbF9pZHhdICsgd29ya2dyb3VwX3NoYXJlZFtsb2NhbF9pZHggKyBjdXJyU2l6ZV07XG4gICAgICB9XG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgfVxuICAgIGlmIChsb2NhbF9pZHggPT0gMCkge1xuICAgICAgbGV0IHN1bV9maW5hbCA9ICR7c3VtVmVjdG9yKCd3b3JrZ3JvdXBfc2hhcmVkWzBdWzBdJywgY29tcG9uZW50cyl9IC8gZjMyKGhpZ2h0ICogJHtjb21wb25lbnRzfSk7XG4gICAgICBsZXQgc3F1YXJlZF9zdW1fZmluYWwgPSAke3N1bVZlY3Rvcignd29ya2dyb3VwX3NoYXJlZFswXVsxXScsIGNvbXBvbmVudHMpfSAvIGYzMihoaWdodCAqICR7Y29tcG9uZW50c30pO1xuXG4gICAgICBsZXQgaW52X3N0ZF9kZXYgPSBpbnZlcnNlU3FydChzcXVhcmVkX3N1bV9maW5hbCAtIHN1bV9maW5hbCAqIHN1bV9maW5hbCArIGYzMigke2Vwc2lsb259KSk7XG4gICAgICBsZXQgY2hhbm5lbF9zY2FsZSA9IGludl9zdGRfZGV2ICogZjMyKHNjYWxlW2NoYW5uZWxdKTtcbiAgICAgIGxldCBjaGFubmVsX3NoaWZ0ID0gZjMyKGJpYXNbY2hhbm5lbF0pIC0gc3VtX2ZpbmFsICogY2hhbm5lbF9zY2FsZTtcbiAgICAgIG91dHB1dFt3b3JrZ3JvdXBfaW5kZXhdID0gdmVjMmYoY2hhbm5lbF9zY2FsZSwgY2hhbm5lbF9zaGlmdCk7XG4gICAgfVxuICB9YDtcbiAgfTtcblxuICByZXR1cm4gY29udGV4dC5jb21wdXRlKFxuICAgIHtcbiAgICAgIG5hbWU6ICdJbnN0YW5jZU5vcm1Db21wdXRlQ2hhbm5lbFNjYWxlU2hpZnQnLFxuICAgICAgLy8gVE9ETzogdXNlIGVwc2lsb24gYXMgdW5pZm9ybS4gQ3VycmVudGx5IGVwc2lsb24gYXMgdW5pZm9ybSBmYWlscyB0ZXN0X2luc3RhbmNlbm9ybV9lcHNpbG9uLlxuICAgICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7Y29tcG9uZW50c307JHtlcHNpbG9ufTske3dvcmtncm91cFNpemV9YCwgaW5wdXREZXBlbmRlbmNpZXMgfSxcbiAgICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogRGF0YVR5cGUuZmxvYXQgfV0sXG4gICAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogdW5pdHNPZldvcmsgfSxcbiAgICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgICAgfSksXG4gICAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgfSxcbiAgICB7IGlucHV0czogW2lucHV0LCBzY2FsZSwgYmlhc10sIG91dHB1dHM6IFstMV0gfSxcbiAgKVswXTtcbn07XG5cbmNvbnN0IGNyZWF0ZUluc3RhbmNlTm9ybVByb2dyYW1JbmZvID0gKFxuICBjb250ZXh0OiBDb21wdXRlQ29udGV4dCxcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IEluc3RhbmNlTm9ybUF0dHJpYnV0ZXMsXG4pID0+IHtcbiAgY29uc3QgeFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0geFNoYXBlO1xuICBjb25zdCBheGlzID0gMjtcbiAgY29uc3QgTiA9IHhTaGFwZVswXTtcbiAgY29uc3QgQyA9IHhTaGFwZVsxXTtcbiAgY29uc3QgSCA9IFNoYXBlVXRpbC5zaXplRnJvbURpbWVuc2lvbih4U2hhcGUsIGF4aXMpO1xuICBjb25zdCBjb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhIKTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIGNvbXBvbmVudHM7XG4gIC8vIGNvbXB1dGUgY2hhbm5lbCBzY2FsZSBhbmQgY2hhbm5lbCBzaGlmdC5cbiAgY29uc3QgY2hhbm5lbFNjYWxlU2hpZnQgPSBjb21wdXRlQ2hhbm5lbFNjYWxlU2hpZnQoXG4gICAgY29udGV4dCxcbiAgICBpbnB1dHNbMF0sXG4gICAgaW5wdXRzWzFdLFxuICAgIGlucHV0c1syXSxcbiAgICBOLFxuICAgIEgsXG4gICAgQyxcbiAgICBhdHRyaWJ1dGVzLmVwc2lsb24sXG4gICk7XG5cbiAgY29uc3QgaW5wdXRTaGFwZSA9IFtOLCBDLCBIIC8gY29tcG9uZW50c107XG4gIGNvbnN0IHNjYWxlU2hhcGUgPSBbTiwgQ107XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWyd0eXBlJywgJ25vbmUnXTtcblxuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCB4ID0gaW5wdXRWYXJpYWJsZSgneCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRTaGFwZS5sZW5ndGgsIGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IHNjYWxlID0gaW5wdXRWYXJpYWJsZSgnc2NhbGVfc2hpZnQnLCBEYXRhVHlwZS5mbG9hdCwgc2NhbGVTaGFwZS5sZW5ndGgsIDIpO1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0U2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCB2YXJpYWJsZXMgPSBbeCwgc2NhbGUsIG91dHB1dF07XG4gICAgcmV0dXJuIGBcbiAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3JtKCdvdXRwdXRfc2l6ZScsICd1MzInKS5kZWNsYXJlVmFyaWFibGVzKC4uLnZhcmlhYmxlcyl9XG4gICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuICAgICAgbGV0IG91dHB1dEluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgICBsZXQgYmF0Y2ggPSBvdXRwdXRJbmRpY2VzWzBdO1xuICAgICAgbGV0IGNoYW5uZWwgPSBvdXRwdXRJbmRpY2VzWzFdO1xuICAgICAgbGV0IHNjYWxlX3NoaWZ0ID0gJHtzY2FsZS5nZXRCeUluZGljZXMoJ3ZlYzI8dTMyPihiYXRjaCwgY2hhbm5lbCknKX07XG4gICAgICBsZXQgdmFsdWUgPSAke3guZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKX0gKiAke291dHB1dC50eXBlLnZhbHVlfShzY2FsZV9zaGlmdC54KSArICR7b3V0cHV0LnR5cGUudmFsdWV9KHNjYWxlX3NoaWZ0LnkpO1xuICAgICAgJHtvdXRwdXQuc2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnLCAndmFsdWUnKX07XG4gIH1gO1xuICB9O1xuXG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICB7XG4gICAgICBuYW1lOiAnSW5zdGFuY2VOb3JtYWxpemF0aW9uJyxcbiAgICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2NvbXBvbmVudHN9YCwgaW5wdXREZXBlbmRlbmNpZXMgfSxcbiAgICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgICAgICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRTaGFwZSwgc2NhbGVTaGFwZSwgaW5wdXRTaGFwZSksXG4gICAgICAgIF0sXG4gICAgICB9KSxcbiAgICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICB9LFxuICAgIHsgaW5wdXRzOiBbaW5wdXRzWzBdLCBjaGFubmVsU2NhbGVTaGlmdF0gfSxcbiAgKTtcbn07XG5cbmNvbnN0IGNyZWF0ZUluc3RhbmNlTm9ybU5IV0NQcm9ncmFtSW5mbyA9IChcbiAgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBJbnN0YW5jZU5vcm1BdHRyaWJ1dGVzLFxuKSA9PiB7XG4gIGNvbnN0IHhTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IHhTaGFwZTtcbiAgY29uc3QgTiA9IHhTaGFwZVswXTtcbiAgY29uc3QgQyA9IHhTaGFwZVt4U2hhcGUubGVuZ3RoIC0gMV07XG4gIGNvbnN0IEggPSBTaGFwZVV0aWwuc2l6ZUZyb21EaW1lbnNpb24oeFNoYXBlLCAxKSAvIEM7XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKEMpO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gY29tcG9uZW50cztcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBIIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IE1hdGguZmxvb3IoQyAvIGNvbXBvbmVudHMpIH0sXG4gIF07XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWyd0eXBlJywgJ3R5cGUnXTtcblxuICAvLyAxLiB0cmFuc3Bvc2UgeCBmcm9tIE5IV0MgdG8gTkNIV1xuICBsZXQgbmVlZFRyYW5zcG9zZSA9IGZhbHNlO1xuICBjb25zdCB0cmFuc3Bvc2VkWFBlcm0gPSBbMCwgeFNoYXBlLmxlbmd0aCAtIDFdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHhTaGFwZS5sZW5ndGggLSAyOyBpKyspIHtcbiAgICBuZWVkVHJhbnNwb3NlID0gbmVlZFRyYW5zcG9zZSB8fCB4U2hhcGVbaSArIDFdICE9PSAxO1xuICAgIHRyYW5zcG9zZWRYUGVybS5wdXNoKGkgKyAxKTtcbiAgfVxuXG4gIG5lZWRUcmFuc3Bvc2UgPSBuZWVkVHJhbnNwb3NlICYmIHhTaGFwZVt4U2hhcGUubGVuZ3RoIC0gMV0gIT09IDE7XG5cbiAgY29uc3QgdHJhbnNwb3NlZFggPSBuZWVkVHJhbnNwb3NlXG4gICAgPyBjb250ZXh0LmNvbXB1dGUoY3JlYXRlVHJhbnNwb3NlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHNbMF0sIHRyYW5zcG9zZWRYUGVybSksIHtcbiAgICAgICAgaW5wdXRzOiBbY29udGV4dC5pbnB1dHNbMF1dLFxuICAgICAgICBvdXRwdXRzOiBbLTFdLFxuICAgICAgfSlbMF1cbiAgICA6IGNvbnRleHQuaW5wdXRzWzBdLnJlc2hhcGUoQXJyYXkuZnJvbSh7IGxlbmd0aDogeFNoYXBlLmxlbmd0aCB9LCAoXywgaSkgPT4geFNoYXBlW3RyYW5zcG9zZWRYUGVybVtpXV0pKTtcbiAgLy8gMi4gY29tcHV0ZSBjaGFubmVsIHNjYWxlIGFuZCBjaGFubmVsIHNoaWZ0LlxuICBjb25zdCBjaGFubmVsU2NhbGVTaGlmdCA9IGNvbXB1dGVDaGFubmVsU2NhbGVTaGlmdChcbiAgICBjb250ZXh0LFxuICAgIHRyYW5zcG9zZWRYLFxuICAgIGlucHV0c1sxXSxcbiAgICBpbnB1dHNbMl0sXG4gICAgTixcbiAgICBILFxuICAgIEMsXG4gICAgYXR0cmlidXRlcy5lcHNpbG9uLFxuICApO1xuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShpbnB1dHNbMF0uZGF0YVR5cGUpO1xuICAgIGNvbnN0IHNjYWxlVHlwZSA9IGNvbXBvbmVudHMgPT09IDEgPyAndmVjMmYnIDogYG1hdCR7Y29tcG9uZW50c314MmZgO1xuICAgIGNvbnN0IHNjYWxlRGF0YSA9IChudW06IG51bWJlcikgPT4ge1xuICAgICAgY29uc3QgaW5kZXggPSBudW0gPT09IDAgPyAneCcgOiAneSc7XG4gICAgICBjb25zdCBmMzJUeXBlID0gY29tcG9uZW50cyA9PT0gMSA/ICdmMzInIDogYHZlYyR7Y29tcG9uZW50c31mYDtcbiAgICAgIHN3aXRjaCAoY29tcG9uZW50cykge1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgcmV0dXJuIGAke2RhdGFUeXBlfSgke2YzMlR5cGV9KHNjYWxlLiR7aW5kZXh9KSlgO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgcmV0dXJuIGB2ZWMyPCR7ZGF0YVR5cGV9Pigke2YzMlR5cGV9KHNjYWxlWzBdLiR7aW5kZXh9LCBzY2FsZVsxXS4ke2luZGV4fSkpYDtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIHJldHVybiBgdmVjNDwke2RhdGFUeXBlfT4oJHtmMzJUeXBlfShzY2FsZVswXS4ke2luZGV4fSwgc2NhbGVbMV0uJHtpbmRleH0sIHNjYWxlWzJdLiR7aW5kZXh9LCBzY2FsZVszXS4ke2luZGV4fSkpYDtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vdCBzdXBwb3J0ZWQgY29tcG9lbnRzICR7Y29tcG9uZW50c31gKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IGlucHV0SGVscGVyID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBvdXRwdXRIZWxwZXIgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZSwgY29tcG9uZW50cyk7XG5cbiAgICByZXR1cm4gYFxuICBAZ3JvdXAoMCkgQGJpbmRpbmcoMCkgdmFyPHN0b3JhZ2UsIHJlYWQ+IGlucHV0IDogYXJyYXk8JHtpbnB1dEhlbHBlci50eXBlLnN0b3JhZ2V9PjtcbiAgQGdyb3VwKDApIEBiaW5kaW5nKDEpIHZhcjxzdG9yYWdlLCByZWFkPiBzY2FsZV9pbnB1dCA6IGFycmF5PCR7c2NhbGVUeXBlfT47XG4gIEBncm91cCgwKSBAYmluZGluZygyKSB2YXI8c3RvcmFnZSwgcmVhZF93cml0ZT4gb3V0cHV0IDogYXJyYXk8JHtvdXRwdXRIZWxwZXIudHlwZS5zdG9yYWdlfT47XG4gIHN0cnVjdCBVbmlmb3JtcyB7SDogdTMyLCBDIDogdTMyfTtcbiAgQGdyb3VwKDApIEBiaW5kaW5nKDMpIHZhcjx1bmlmb3JtPiB1bmlmb3JtczogVW5pZm9ybXM7XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgbGV0IGN1cnJlbnRfaW1hZ2VfbnVtYmVyID0gZ2xvYmFsX2lkeCAvICh1bmlmb3Jtcy5DICogdW5pZm9ybXMuSCk7XG4gICAgbGV0IGN1cnJlbnRfY2hhbm5lbF9udW1iZXIgPSBnbG9iYWxfaWR4ICUgdW5pZm9ybXMuQztcblxuICAgIGxldCBzY2FsZV9vZmZzZXQgPSBjdXJyZW50X2ltYWdlX251bWJlciAqIHVuaWZvcm1zLkMgKyBjdXJyZW50X2NoYW5uZWxfbnVtYmVyO1xuICAgIGxldCBzY2FsZSA9IHNjYWxlX2lucHV0W3NjYWxlX29mZnNldF07XG4gICAgb3V0cHV0W2dsb2JhbF9pZHhdID0gZm1hKGlucHV0W2dsb2JhbF9pZHhdLCAke3NjYWxlRGF0YSgwKX0sICR7c2NhbGVEYXRhKDEpfSk7XG4gIH1gO1xuICB9O1xuICBjb250ZXh0LmNvbXB1dGUoXG4gICAge1xuICAgICAgbmFtZTogJ0luc3RhbmNlTm9ybWFsaXphdGlvbk5IV0MnLFxuICAgICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7Y29tcG9uZW50c31gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfV0sXG4gICAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgICAgfSksXG4gICAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgfSxcbiAgICB7IGlucHV0czogW2lucHV0c1swXSwgY2hhbm5lbFNjYWxlU2hpZnRdIH0sXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgaW5zdGFuY2VOb3JtID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBJbnN0YW5jZU5vcm1BdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGlmIChhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnKSB7XG4gICAgY3JlYXRlSW5zdGFuY2VOb3JtTkhXQ1Byb2dyYW1JbmZvKGNvbnRleHQsIGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIHtcbiAgICBjcmVhdGVJbnN0YW5jZU5vcm1Qcm9ncmFtSW5mbyhjb250ZXh0LCBjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeSwgUHJvZ3JhbVVuaWZvcm0gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7XG4gIGNhc3RUb0YzMixcbiAgZmlsbFZlY3RvcixcbiAgZ2V0TWF4Q29tcG9uZW50cyxcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgc3VtVmVjdG9yLFxuICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUsXG4gIFVuaWZvcm1zQXJyYXlUeXBlLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbmludGVyZmFjZSBMYXllck5vcm1BdHRyaWJ1dGVzIHtcbiAgc2ltcGxpZmllZDogYm9vbGVhbjtcbiAgYXhpczogbnVtYmVyO1xuICBlcHNpbG9uOiBudW1iZXI7XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggPCAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdsYXllck5vcm0gcmVxdWlyZXMgYXQgbGVhc3QgMiBpbnB1dHMuJyk7XG4gIH1cbn07XG5cbmNvbnN0IGNyZWF0ZUxheWVyTm9ybVByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogTGF5ZXJOb3JtQXR0cmlidXRlcyxcbiAgb3V0cHV0Q291bnQ6IG51bWJlcixcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3Qgc2ltcGxpZmllZCA9IGF0dHJpYnV0ZXMuc2ltcGxpZmllZDtcblxuICBjb25zdCB4U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3Qgc2NhbGUgPSBpbnB1dHNbMV07XG4gIGNvbnN0IGJpYXMgPSAhc2ltcGxpZmllZCAmJiBpbnB1dHNbMl07XG5cbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSB4U2hhcGU7XG4gIGNvbnN0IGF4aXMgPSBTaGFwZVV0aWwubm9ybWFsaXplQXhpcyhhdHRyaWJ1dGVzLmF4aXMsIHhTaGFwZS5sZW5ndGgpO1xuICBjb25zdCBub3JtQ291bnQgPSBTaGFwZVV0aWwuc2l6ZVRvRGltZW5zaW9uKHhTaGFwZSwgYXhpcyk7XG4gIGNvbnN0IG5vcm1TaXplID0gU2hhcGVVdGlsLnNpemVGcm9tRGltZW5zaW9uKHhTaGFwZSwgYXhpcyk7XG5cbiAgY29uc3Qgc2NhbGVTaXplID0gU2hhcGVVdGlsLnNpemUoc2NhbGUuZGltcyk7XG4gIGNvbnN0IGJpYXNTaXplID0gYmlhcyA/IFNoYXBlVXRpbC5zaXplKGJpYXMuZGltcykgOiAwO1xuICBpZiAoc2NhbGVTaXplICE9PSBub3JtU2l6ZSB8fCAoYmlhcyAmJiBiaWFzU2l6ZSAhPT0gbm9ybVNpemUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBTaXplIG9mIFguc2hhcGUoKVtheGlzOl0gPT0gJHtub3JtU2l6ZX0uXG4gICAgICAgU2l6ZSBvZiBzY2FsZSBhbmQgYmlhcyAoaWYgcHJvdmlkZWQpIG11c3QgbWF0Y2ggdGhpcy5cbiAgICAgICBHb3Qgc2NhbGUgc2l6ZSBvZiAke3NjYWxlU2l6ZX0gYW5kIGJpYXMgc2l6ZSBvZiAke2JpYXNTaXplfWApO1xuICB9XG5cbiAgY29uc3QgbWVhbkludlN0ZERldkRpbTogbnVtYmVyW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB4U2hhcGUubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoaSA8IGF4aXMpIHtcbiAgICAgIG1lYW5JbnZTdGREZXZEaW0ucHVzaCh4U2hhcGVbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBtZWFuSW52U3RkRGV2RGltLnB1c2goMSk7XG4gICAgfVxuICB9XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKG5vcm1TaXplKTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3R5cGUnLCAndHlwZSddO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG5vcm1Db3VudCB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IG5vcm1TaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IE1hdGguZmxvb3Iobm9ybVNpemUgLyBjb21wb25lbnRzKSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IGF0dHJpYnV0ZXMuZXBzaWxvbiB9LFxuICBdO1xuICBpZiAoYmlhcykge1xuICAgIGlucHV0RGVwZW5kZW5jaWVzLnB1c2goJ3R5cGUnKTtcbiAgfVxuICBjb25zdCBoYXNNZWFuRGF0YU91dHB1dCA9IG91dHB1dENvdW50ID4gMTtcbiAgY29uc3QgaGFzSW52U3RkT3V0cHV0ID0gb3V0cHV0Q291bnQgPiAyO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGRhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKGlucHV0c1swXS5kYXRhVHlwZSk7XG4gICAgY29uc3QgdmFyaWFibGVzID0gW1xuICAgICAgaW5wdXRWYXJpYWJsZSgneCcsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMsIGNvbXBvbmVudHMpLFxuICAgICAgaW5wdXRWYXJpYWJsZSgnc2NhbGUnLCBzY2FsZS5kYXRhVHlwZSwgc2NhbGUuZGltcywgY29tcG9uZW50cyksXG4gICAgXTtcbiAgICBpZiAoYmlhcykge1xuICAgICAgdmFyaWFibGVzLnB1c2goaW5wdXRWYXJpYWJsZSgnYmlhcycsIGJpYXMuZGF0YVR5cGUsIGJpYXMuZGltcywgY29tcG9uZW50cykpO1xuICAgIH1cbiAgICB2YXJpYWJsZXMucHVzaChvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZSwgY29tcG9uZW50cykpO1xuICAgIGlmIChoYXNNZWFuRGF0YU91dHB1dCkge1xuICAgICAgdmFyaWFibGVzLnB1c2gob3V0cHV0VmFyaWFibGUoJ21lYW5fZGF0YV9vdXRwdXQnLCBEYXRhVHlwZS5mbG9hdCwgbWVhbkludlN0ZERldkRpbSkpO1xuICAgIH1cbiAgICBpZiAoaGFzSW52U3RkT3V0cHV0KSB7XG4gICAgICB2YXJpYWJsZXMucHVzaChvdXRwdXRWYXJpYWJsZSgnaW52X3N0ZF9vdXRwdXQnLCBEYXRhVHlwZS5mbG9hdCwgbWVhbkludlN0ZERldkRpbSkpO1xuICAgIH1cblxuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ25vcm1fY291bnQnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnbm9ybV9zaXplJywgdHlwZTogJ2YzMicgfSxcbiAgICAgIHsgbmFtZTogJ25vcm1fc2l6ZV92ZWN0b3JpemVkJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2Vwc2lsb24nLCB0eXBlOiAnZjMyJyB9LFxuICAgIF07XG4gICAgcmV0dXJuIGBcbiAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi52YXJpYWJsZXMpfVxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5ub3JtX2NvdW50Jyl9XG4gICAgbGV0IG9mZnNldCA9IGdsb2JhbF9pZHggKiB1bmlmb3Jtcy5ub3JtX3NpemVfdmVjdG9yaXplZDtcbiAgICB2YXIgbWVhbl92ZWN0b3IgPSAke2ZpbGxWZWN0b3IoJ2YzMicsIGNvbXBvbmVudHMpfTtcbiAgICB2YXIgbWVhbl9zcXVhcmVfdmVjdG9yID0gJHtmaWxsVmVjdG9yKCdmMzInLCBjb21wb25lbnRzKX07XG5cbiAgICBmb3IgKHZhciBoOiB1MzIgPSAwdTsgaCA8IHVuaWZvcm1zLm5vcm1fc2l6ZV92ZWN0b3JpemVkOyBoKyspIHtcbiAgICAgIGxldCB2YWx1ZSA9ICR7Y2FzdFRvRjMyKGRhdGFUeXBlLCBjb21wb25lbnRzLCAneFtoICsgb2Zmc2V0XScpfTtcbiAgICAgIG1lYW5fdmVjdG9yICs9IHZhbHVlO1xuICAgICAgbWVhbl9zcXVhcmVfdmVjdG9yICs9IHZhbHVlICogdmFsdWU7XG4gICAgfVxuICAgIGxldCBtZWFuID0gJHtzdW1WZWN0b3IoJ21lYW5fdmVjdG9yJywgY29tcG9uZW50cyl9IC8gdW5pZm9ybXMubm9ybV9zaXplO1xuICAgIGxldCBpbnZfc3RkX2RldiA9IGludmVyc2VTcXJ0KCR7c3VtVmVjdG9yKCdtZWFuX3NxdWFyZV92ZWN0b3InLCBjb21wb25lbnRzKX0gLyB1bmlmb3Jtcy5ub3JtX3NpemUgJHtcbiAgICAgIHNpbXBsaWZpZWQgPyAnJyA6ICctIG1lYW4gKiBtZWFuJ1xuICAgIH0gKyB1bmlmb3Jtcy5lcHNpbG9uKTtcblxuICAgIGZvciAodmFyIGo6IHUzMiA9IDA7IGogPCB1bmlmb3Jtcy5ub3JtX3NpemVfdmVjdG9yaXplZDsgaisrKSB7XG4gICAgICBsZXQgZjMyaW5wdXQgPSAke2Nhc3RUb0YzMihkYXRhVHlwZSwgY29tcG9uZW50cywgJ3hbaiArIG9mZnNldF0nKX07XG4gICAgICBsZXQgZjMyc2NhbGUgPSAke2Nhc3RUb0YzMihkYXRhVHlwZSwgY29tcG9uZW50cywgJ3NjYWxlW2pdJyl9O1xuICAgICAgb3V0cHV0W2ogKyBvZmZzZXRdID0gJHt2YXJpYWJsZXNbMF0udHlwZS52YWx1ZX0oKGYzMmlucHV0ICR7c2ltcGxpZmllZCA/ICcnIDogJy0gbWVhbid9KSAqIGludl9zdGRfZGV2ICogZjMyc2NhbGVcbiAgICAgICAgJHtiaWFzID8gYCsgJHtjYXN0VG9GMzIoZGF0YVR5cGUsIGNvbXBvbmVudHMsICdiaWFzW2pdJyl9YCA6ICcnfVxuICAgICAgKTtcbiAgICB9XG5cbiAgICAke2hhc01lYW5EYXRhT3V0cHV0ID8gJ21lYW5fZGF0YV9vdXRwdXRbZ2xvYmFsX2lkeF0gPSBtZWFuJyA6ICcnfTtcbiAgICAke2hhc0ludlN0ZE91dHB1dCA/ICdpbnZfc3RkX291dHB1dFtnbG9iYWxfaWR4XSA9IGludl9zdGRfZGV2JyA6ICcnfTtcbiAgfWA7XG4gIH07XG4gIGNvbnN0IG91dHB1dHMgPSBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9XTtcbiAgaWYgKGhhc01lYW5EYXRhT3V0cHV0KSB7XG4gICAgb3V0cHV0cy5wdXNoKHsgZGltczogbWVhbkludlN0ZERldkRpbSwgZGF0YVR5cGU6IERhdGFUeXBlLmZsb2F0IH0pO1xuICB9XG4gIGlmIChoYXNJbnZTdGRPdXRwdXQpIHtcbiAgICBvdXRwdXRzLnB1c2goeyBkaW1zOiBtZWFuSW52U3RkRGV2RGltLCBkYXRhVHlwZTogRGF0YVR5cGUuZmxvYXQgfSk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdMYXllck5vcm1hbGl6YXRpb24nLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2NvbXBvbmVudHN9OyR7b3V0cHV0Q291bnR9OyR7c2ltcGxpZmllZH1gLCBpbnB1dERlcGVuZGVuY2llcyB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwobm9ybUNvdW50IC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGxheWVyTm9ybSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogTGF5ZXJOb3JtQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVMYXllck5vcm1Qcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcywgY29udGV4dC5vdXRwdXRDb3VudCkpO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IEJyb2FkY2FzdFV0aWwsIFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQgfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZU5haXZlTWF0bXVsUHJvZ3JhbUluZm8gfSBmcm9tICcuL21hdG11bC1zaGFkZXJzJztcbmltcG9ydCB7IGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvIH0gZnJvbSAnLi8zcmQtcGFydHkvbWF0bXVsX3BhY2tlZF93ZWJncHUnO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNYXRNdWwgcmVxdWlyZXMgMiBpbnB1dHMuJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLmRpbXNbaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMV0gIT09IGlucHV0c1sxXS5kaW1zW2lucHV0c1sxXS5kaW1zLmxlbmd0aCAtIDJdKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzaGFyZWQgZGltZW5zaW9uIGRvZXMgbm90IG1hdGNoLicpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgbWF0TXVsID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBCcm9hZGNhc3RVdGlsLmNhbGNTaGFwZShjb250ZXh0LmlucHV0c1swXS5kaW1zLCBjb250ZXh0LmlucHV0c1sxXS5kaW1zLCB0cnVlKTtcbiAgaWYgKCFvdXRwdXRTaGFwZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNhbid0IHVzZSBtYXRtdWwgb24gdGhlIGdpdmVuIHRlbnNvcnNcIik7XG4gIH1cbiAgY29uc3QgTiA9IG91dHB1dFNoYXBlW291dHB1dFNoYXBlLmxlbmd0aCAtIDFdO1xuICBjb25zdCBLID0gY29udGV4dC5pbnB1dHNbMF0uZGltc1tjb250ZXh0LmlucHV0c1swXS5kaW1zLmxlbmd0aCAtIDFdO1xuICBpZiAoTiA8IDggJiYgSyA8IDgpIHtcbiAgICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlTmFpdmVNYXRtdWxQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgeyBhY3RpdmF0aW9uOiAnJyB9LCBvdXRwdXRTaGFwZSkpO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IE0gPSBvdXRwdXRTaGFwZVtvdXRwdXRTaGFwZS5sZW5ndGggLSAyXTtcbiAgICBjb25zdCBiYXRjaEEgPSBTaGFwZVV0aWwuc2l6ZShjb250ZXh0LmlucHV0c1swXS5kaW1zLnNsaWNlKDAsIC0yKSk7XG4gICAgY29uc3QgYmF0Y2hCID0gU2hhcGVVdGlsLnNpemUoY29udGV4dC5pbnB1dHNbMV0uZGltcy5zbGljZSgwLCAtMikpO1xuICAgIGlmIChiYXRjaEEgIT09IDEgJiYgTSA9PT0gMSAmJiBiYXRjaEIgPT09IDEpIHtcbiAgICAgIC8vIE9wdGltaXphdGlvbiBmb3IgYmF0Y2hlZCB2ZWMtbWF0LW11bFxuICAgICAgY29uc3QgcmVzaGFwZWRBID0gY29udGV4dC5pbnB1dHNbMF0ucmVzaGFwZShbMSwgYmF0Y2hBLCBLXSk7XG4gICAgICBjb25zdCByZXNoYXBlZEIgPSBjb250ZXh0LmlucHV0c1sxXS5yZXNoYXBlKFsxLCBLLCBOXSk7XG4gICAgICBjb25zdCBtYXRtdWxPdXRwdXRTaGFwZSA9IFsxLCBiYXRjaEEsIE5dO1xuICAgICAgY29uc3QgbWF0bXVsSW5wdXRzID0gW3Jlc2hhcGVkQSwgcmVzaGFwZWRCXTtcbiAgICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVNYXRtdWxQcm9ncmFtSW5mbyhtYXRtdWxJbnB1dHMsIHsgYWN0aXZhdGlvbjogJycgfSwgb3V0cHV0U2hhcGUsIG1hdG11bE91dHB1dFNoYXBlKSwge1xuICAgICAgICBpbnB1dHM6IG1hdG11bElucHV0cyxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlTWF0bXVsUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIHsgYWN0aXZhdGlvbjogJycgfSwgb3V0cHV0U2hhcGUpKTtcbiAgICB9XG4gIH1cbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGdldE1heENvbXBvbmVudHMsXG4gIGlucHV0VmFyaWFibGUsXG4gIG91dHB1dFZhcmlhYmxlLFxuICBTaGFkZXJIZWxwZXIsXG4gIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSxcbn0gZnJvbSAnLi9jb21tb24nO1xuXG4vLyAgVE9ETyBzdXBwb3J0IHF1YW50aXphdGlvbiBiaXRzIG5vdCBlcXVhbCB0byA0XG5leHBvcnQgaW50ZXJmYWNlIE1hdE11bE5CaXRzQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIGs6IG51bWJlcjtcbiAgbjogbnVtYmVyO1xuICBhY2N1cmFjeUxldmVsOiBudW1iZXI7XG4gIGJpdHM6IG51bWJlcjtcbiAgYmxvY2tTaXplOiBudW1iZXI7XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBNYXRNdWxOQml0c0F0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKGlucHV0cy5sZW5ndGggPCAzIHx8IGlucHV0cy5sZW5ndGggPiA0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNYXRNdWxOQml0cyByZXF1aXJlcyAzIG9yIDQgaW5wdXRzJyk7XG4gIH1cbiAgY29uc3QgYSA9IGlucHV0c1swXTtcbiAgY29uc3QgYVJhbmsgPSBhLmRpbXMubGVuZ3RoO1xuICBpZiAoYS5kaW1zW2FSYW5rIC0gMV0gIT09IGF0dHJpYnV0ZXMuaykge1xuICAgIHRocm93IG5ldyBFcnJvcignVGhlIGxhc3QgZGltIG9mIGlucHV0IHNoYXBlIGRvZXMgbm90IG1hdGNoIHRoZSBrIHZhbHVlJyk7XG4gIH1cbiAgY29uc3QgbkJsb2Nrc1BlckNvbCA9IE1hdGguZmxvb3IoKGF0dHJpYnV0ZXMuayArIGF0dHJpYnV0ZXMuYmxvY2tTaXplIC0gMSkgLyBhdHRyaWJ1dGVzLmJsb2NrU2l6ZSk7XG4gIGNvbnN0IGJsb2JTaXplID0gKGF0dHJpYnV0ZXMuYmxvY2tTaXplIC8gOCkgKiBhdHRyaWJ1dGVzLmJpdHM7XG4gIGNvbnN0IGIgPSBpbnB1dHNbMV07XG4gIGlmICghU2hhcGVVdGlsLmFyZUVxdWFsKGIuZGltcywgW2F0dHJpYnV0ZXMubiwgbkJsb2Nrc1BlckNvbCwgYmxvYlNpemVdKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignVGhlIHNlY29uZCBpbnB1dHMgbXVzdCBiZSAzRCB0ZW5zb3Igd2l0aCBzaGFwZSBOIFggbkJsb2Nrc1BlckNvbCBYIGJsb2JTaXplJyk7XG4gIH1cbiAgY29uc3Qgc2NhbGVzID0gaW5wdXRzWzJdO1xuICBjb25zdCBzY2FsZXNTaGFwZSA9IHNjYWxlcy5kaW1zO1xuICBpZiAoU2hhcGVVdGlsLnNpemUoc2NhbGVzU2hhcGUpICE9PSBhdHRyaWJ1dGVzLm4gKiBuQmxvY2tzUGVyQ29sKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzY2FsZXMgaW5wdXQgc2l6ZSBlcnJvci4nKTtcbiAgfVxuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gNCkge1xuICAgIGNvbnN0IHplcm9Qb2ludHMgPSBpbnB1dHNbM107XG4gICAgY29uc3QgemVyb1BvaW50c1NoYXBlID0gemVyb1BvaW50cy5kaW1zO1xuICAgIGNvbnN0IGV4cGVjdGVkWmVyb1BvaW50c1NpemUgPVxuICAgICAgYXR0cmlidXRlcy5iaXRzID4gNCA/IGF0dHJpYnV0ZXMubiAqIG5CbG9ja3NQZXJDb2wgOiBhdHRyaWJ1dGVzLm4gKiBNYXRoLmZsb29yKChuQmxvY2tzUGVyQ29sICsgMSkgLyAyKTtcbiAgICBpZiAoU2hhcGVVdGlsLnNpemUoemVyb1BvaW50c1NoYXBlKSAhPT0gZXhwZWN0ZWRaZXJvUG9pbnRzU2l6ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd6ZXJvUG9pbnRzIGlucHV0IHNpemUgZXJyb3IuJyk7XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlTWF0TXVsTkJpdHNQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGF0dHJpYnV0ZXM6IE1hdE11bE5CaXRzQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBhUmFuayA9IGlucHV0U2hhcGUubGVuZ3RoO1xuICBjb25zdCBkaW1BT3V0ZXIgPSBpbnB1dFNoYXBlW2FSYW5rIC0gMl07XG4gIGNvbnN0IGRpbUlubmVyID0gYXR0cmlidXRlcy5rO1xuICBjb25zdCBkaW1CT3V0ZXIgPSBhdHRyaWJ1dGVzLm47XG4gIGNvbnN0IGJhdGNoRGltcyA9IGlucHV0U2hhcGUuc2xpY2UoMCwgYVJhbmsgLSAyKTtcbiAgY29uc3QgYmF0Y2hTaXplID0gU2hhcGVVdGlsLnNpemUoYmF0Y2hEaW1zKTtcbiAgY29uc3QgYmxvYlNpemUgPSBpbnB1dHNbMV0uZGltc1syXTtcbiAgY29uc3QgYmxvYlNpemVJbldvcmRzID0gYmxvYlNpemUgLyA0O1xuICBjb25zdCBkYXRhVHlwZSA9IGlucHV0c1swXS5kYXRhVHlwZTtcbiAgY29uc3QgYUNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKGF0dHJpYnV0ZXMuayk7XG4gIGNvbnN0IGJDb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhibG9iU2l6ZUluV29yZHMpO1xuICBjb25zdCBjb21wb25lbnRzID0gZ2V0TWF4Q29tcG9uZW50cyhkaW1CT3V0ZXIpO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGJhdGNoRGltcy5jb25jYXQoW2RpbUFPdXRlciwgZGltQk91dGVyXSk7XG4gIGNvbnN0IG91dHB1dE51bWJlciA9IGRpbUFPdXRlciA+IDEgJiYgKGRpbUJPdXRlciAvIGNvbXBvbmVudHMpICUgMiA9PT0gMCA/IDIgOiAxO1xuICBjb25zdCBkaXNwYXRjaFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyBjb21wb25lbnRzIC8gb3V0cHV0TnVtYmVyO1xuXG4gIGNvbnN0IHdvcmtncm91cFNpemUgPSA2NDtcblxuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXTtcbiAgY29uc3QgaW5wdXRTaGFwZVRlbXAgPSBbYmF0Y2hTaXplLCBkaW1BT3V0ZXIsIGRpbUlubmVyIC8gYUNvbXBvbmVudHNdO1xuICBjb25zdCBiU2hhcGUgPSBTaGFwZVV0aWwuY29udmVydFNoYXBlKGlucHV0c1sxXS5kaW1zKS5zbGljZSgpO1xuICBiU2hhcGUuc3BsaWNlKC0xLCAxLCBibG9iU2l6ZUluV29yZHMgLyBiQ29tcG9uZW50cyk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0U2hhcGVUZW1wKSk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGJTaGFwZSkpO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dHNbMl0uZGltcykpO1xuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gNCkge1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKFNoYXBlVXRpbC5jb252ZXJ0U2hhcGUoaW5wdXRzWzNdLmRpbXMpKSk7XG4gIH1cbiAgY29uc3Qgb3V0cHV0U2hhcGVUZW1wID0gW2JhdGNoU2l6ZSwgZGltQU91dGVyLCBkaW1CT3V0ZXIgLyBjb21wb25lbnRzXTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0cHV0U2hhcGVUZW1wKSk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgaW5wdXRSYW5rID0gaW5wdXRTaGFwZVRlbXAubGVuZ3RoO1xuICAgIGNvbnN0IGEgPSBpbnB1dFZhcmlhYmxlKCdhJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dFJhbmssIGFDb21wb25lbnRzKTtcbiAgICBjb25zdCBiID0gaW5wdXRWYXJpYWJsZSgnYicsIERhdGFUeXBlLnVpbnQzMiwgYlNoYXBlLmxlbmd0aCwgYkNvbXBvbmVudHMpO1xuICAgIGNvbnN0IHNjYWxlcyA9IGlucHV0VmFyaWFibGUoJ3NjYWxlcycsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBpbnB1dFZhcmlhYmxlcyA9IFthLCBiLCBzY2FsZXNdO1xuICAgIGNvbnN0IHplcm9Qb2ludHMgPVxuICAgICAgaW5wdXRzLmxlbmd0aCA9PT0gNCA/IGlucHV0VmFyaWFibGUoJ3plcm9fcG9pbnRzJywgRGF0YVR5cGUudWludDMyLCBpbnB1dHNbM10uZGltcy5sZW5ndGgpIDogdW5kZWZpbmVkO1xuICAgIGlmICh6ZXJvUG9pbnRzKSB7XG4gICAgICBpbnB1dFZhcmlhYmxlcy5wdXNoKHplcm9Qb2ludHMpO1xuICAgIH1cbiAgICBjb25zdCBvdXRwdXRSYW5rID0gb3V0cHV0U2hhcGVUZW1wLmxlbmd0aDtcbiAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRSYW5rLCBjb21wb25lbnRzKTtcbiAgICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShpbnB1dHNbMF0uZGF0YVR5cGUpO1xuXG4gICAgY29uc3QgcURxRGF0YVR5cGUgPSAoKCkgPT4ge1xuICAgICAgc3dpdGNoIChhQ29tcG9uZW50cykge1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgcmV0dXJuIGBhcnJheTwke2RhdGFUeXBlfSwgOD5gO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgcmV0dXJuIGBtYXQ0eDI8JHtkYXRhVHlwZX0+YDtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIHJldHVybiBgbWF0Mng0PCR7ZGF0YVR5cGV9PmA7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2FDb21wb25lbnRzfS1jb21wb25lbnQgaXMgbm90IHN1cHBvcnRlZC5gKTtcbiAgICAgIH1cbiAgICB9KSgpO1xuXG4gICAgY29uc3QgcHJvY2Vzc09uZVdvcmQgPSAoKTogc3RyaW5nID0+IHtcbiAgICAgIGxldCBjYWxjU3RyID0gYFxuICAgICAgICAgIC8vIHJldXNlIGEgZGF0YVxuICAgICAgICAgICAgdmFyIGlucHV0X29mZnNldCA9ICR7YS5pbmRpY2VzVG9PZmZzZXQoYCR7YS50eXBlLmluZGljZXN9KGJhdGNoLCByb3csIHdvcmRfb2Zmc2V0KWApfTtcbiAgICAgICAgICAgIHZhciBhX2RhdGE6ICR7cURxRGF0YVR5cGV9O1xuICAgICAgICAgICAgZm9yICh2YXIgajogdTMyID0gMDsgaiA8ICR7OCAvIGFDb21wb25lbnRzfTsgaisrKSB7XG4gICAgICAgICAgICAgIGFfZGF0YVtqXSA9ICR7YS5nZXRCeU9mZnNldCgnaW5wdXRfb2Zmc2V0Jyl9O1xuICAgICAgICAgICAgICBpbnB1dF9vZmZzZXQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICBgO1xuICAgICAgZm9yIChsZXQgYyA9IDA7IGMgPCBjb21wb25lbnRzICogb3V0cHV0TnVtYmVyOyBjKyspIHtcbiAgICAgICAgY2FsY1N0ciArPSBgXG4gICAgICAgICAgICBiX3ZhbHVlID0gJHtiQ29tcG9uZW50cyA9PT0gMSA/IGBiJHtjfV9kYXRhYCA6IGBiJHtjfV9kYXRhW2ldYH07XG4gICAgICAgICAgICBiX3ZhbHVlX2xvd2VyID0gdW5wYWNrNHhVOChiX3ZhbHVlICYgYl9tYXNrKTtcbiAgICAgICAgICAgIGJfdmFsdWVfdXBwZXIgPSB1bnBhY2s0eFU4KChiX3ZhbHVlID4+IDQpICYgYl9tYXNrKTtcbiAgICAgICAgICAgIGJfcXVhbnRpemVkX3ZhbHVlcyA9ICR7cURxRGF0YVR5cGV9KCR7QXJyYXkuZnJvbShcbiAgICAgICAgICAgICAgeyBsZW5ndGg6IDQgfSxcbiAgICAgICAgICAgICAgKF8sIGkpID0+IGAke2RhdGFUeXBlfShiX3ZhbHVlX2xvd2VyWyR7aX1dKSwgJHtkYXRhVHlwZX0oYl92YWx1ZV91cHBlclske2l9XSlgLFxuICAgICAgICAgICAgKS5qb2luKCcsICcpfSk7XG4gICAgICAgICAgICBiX2RlcXVhbnRpemVkX3ZhbHVlcyA9ICR7KCgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKGFDb21wb25lbnRzID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGAke3FEcURhdGFUeXBlfSgke0FycmF5LmZyb20oXG4gICAgICAgICAgICAgICAgICB7IGxlbmd0aDogOCB9LFxuICAgICAgICAgICAgICAgICAgKF8sIGkpID0+IGAoYl9xdWFudGl6ZWRfdmFsdWVzWyR7aX1dIC0gJHt6ZXJvUG9pbnRzID8gYHplcm9fcG9pbnQke2N9YCA6ICd6ZXJvX3BvaW50J30pICogc2NhbGUke2N9YCxcbiAgICAgICAgICAgICAgICApLmpvaW4oJywgJyl9KTtgO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBgKGJfcXVhbnRpemVkX3ZhbHVlcyAtICR7cURxRGF0YVR5cGV9KCR7QXJyYXkoOClcbiAgICAgICAgICAgICAgICAgIC5maWxsKGAke3plcm9Qb2ludHMgPyBgemVyb19wb2ludCR7Y31gIDogJ3plcm9fcG9pbnQnfWApXG4gICAgICAgICAgICAgICAgICAuam9pbignLCcpfSkpICogc2NhbGUke2N9O2A7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKCl9O1xuICAgICAgICAgICAgd29ya2dyb3VwX3NoYXJlZFtsb2NhbF9pZC54ICogJHtvdXRwdXROdW1iZXJ9ICsgJHtNYXRoLmZsb29yKGMgLyBjb21wb25lbnRzKX1dJHtjb21wb25lbnRzID4gMSA/IGBbJHtjICUgY29tcG9uZW50c31dYCA6ICcnfSArPSAke0FycmF5LmZyb20oXG4gICAgICAgICAgICAgIHsgbGVuZ3RoOiA4IC8gYUNvbXBvbmVudHMgfSxcbiAgICAgICAgICAgICAgKF8sIGkpID0+XG4gICAgICAgICAgICAgICAgYCR7XG4gICAgICAgICAgICAgICAgICBhQ29tcG9uZW50cyA9PT0gMVxuICAgICAgICAgICAgICAgICAgICA/IGBhX2RhdGFbJHtpfV0gKiBiX2RlcXVhbnRpemVkX3ZhbHVlc1ske2l9XWBcbiAgICAgICAgICAgICAgICAgICAgOiBgZG90KGFfZGF0YVske2l9XSwgYl9kZXF1YW50aXplZF92YWx1ZXNbJHtpfV0pYFxuICAgICAgICAgICAgICAgIH1gLFxuICAgICAgICAgICAgKS5qb2luKCcgKyAnKX07XG4gICAgICAgICAgYDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjYWxjU3RyO1xuICAgIH07XG4gICAgY29uc3QgcHJlcGFyZVNjYWxlQW5kWmVyb1BvaW50ID0gKCk6IHN0cmluZyA9PiB7XG4gICAgICBsZXQgY2FsY1N0ciA9IGBcbiAgICAgICAgICAgIHZhciBjb2xfaW5kZXggPSBjb2wgKiAke2NvbXBvbmVudHN9O1xuICAgICAgICAgICAgJHtcbiAgICAgICAgICAgICAgemVyb1BvaW50c1xuICAgICAgICAgICAgICAgID8gYFxuICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfYnl0ZXNfcGVyX2NvbCA9IChuQmxvY2tzUGVyQ29sICsgMSkgLyAyO1xuICAgICAgICAgICAgdmFyIHplcm9fcG9pbnRfYnl0ZV9jb3VudDogdTMyO1xuICAgICAgICAgICAgdmFyIHplcm9fcG9pbnRfd29yZF9pbmRleDogdTMyO1xuICAgICAgICAgICAgdmFyIHplcm9fcG9pbnRfYnl0ZV9vZmZzZXQ6IHUzMjtcbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X25pYmJsZV9vZmZzZXQ6IHUzMiA9IGJsb2NrICYgMHgxdTtcbiAgICAgICAgICAgIHZhciB6ZXJvX3BvaW50X2JpdHNfb2Zmc2V0OiB1MzI7XG4gICAgICAgICAgICB2YXIgemVyb19wb2ludF93b3JkOiB1MzI7YFxuICAgICAgICAgICAgICAgIDogYFxuICAgICAgICAgICAgLy8gVGhlIGRlZmF1bHQgemVybyBwb2ludCBpcyA4IGZvciB1bnNpZ25lZCA0LWJpdCBxdWFudGl6YXRpb24uXG4gICAgICAgICAgICBsZXQgemVyb19wb2ludCA9ICR7ZGF0YVR5cGV9KCR7OC4wfSk7YFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYDtcbiAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgY29tcG9uZW50cyAqIG91dHB1dE51bWJlcjsgYysrKSB7XG4gICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgICAgbGV0IHNjYWxlJHtjfSA9ICR7c2NhbGVzLmdldEJ5T2Zmc2V0KGBjb2xfaW5kZXggKiBuQmxvY2tzUGVyQ29sICsgYmxvY2tgKX07XG4gICAgICAgICAgICAke1xuICAgICAgICAgICAgICB6ZXJvUG9pbnRzXG4gICAgICAgICAgICAgICAgPyBgXG4gICAgICAgICAgICB6ZXJvX3BvaW50X2J5dGVfY291bnQgPSBjb2xfaW5kZXggKiB6ZXJvX3BvaW50X2J5dGVzX3Blcl9jb2wgKyAoYmxvY2sgPj4gMHgxdSk7XG4gICAgICAgICAgICB6ZXJvX3BvaW50X3dvcmRfaW5kZXggPSB6ZXJvX3BvaW50X2J5dGVfY291bnQgPj4gMHgydTtcbiAgICAgICAgICAgIHplcm9fcG9pbnRfYnl0ZV9vZmZzZXQgPSB6ZXJvX3BvaW50X2J5dGVfY291bnQgJiAweDN1O1xuICAgICAgICAgICAgemVyb19wb2ludF9iaXRzX29mZnNldCA9ICh6ZXJvX3BvaW50X2J5dGVfb2Zmc2V0IDw8IDMpICsgKHplcm9fcG9pbnRfbmliYmxlX29mZnNldCA8PCAyKTtcbiAgICAgICAgICAgIHplcm9fcG9pbnRfd29yZCA9ICR7emVyb1BvaW50cy5nZXRCeU9mZnNldCgnemVyb19wb2ludF93b3JkX2luZGV4Jyl9ID4+IHplcm9fcG9pbnRfYml0c19vZmZzZXQ7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludCR7Y30gPSAke2RhdGFUeXBlfSgoemVyb19wb2ludF93b3JkKSAmIDB4RnUpO2BcbiAgICAgICAgICAgICAgICA6ICcnXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb2xfaW5kZXggKz0gMTtgO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNhbGNTdHI7XG4gICAgfTtcbiAgICBjb25zdCBwcmVwYXJlQkRhdGEgPSAoKTogc3RyaW5nID0+IHtcbiAgICAgIGxldCBjYWxjU3RyID0gYGNvbF9pbmRleCA9IGNvbCAqICR7Y29tcG9uZW50c307YDtcbiAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgY29tcG9uZW50cyAqIG91dHB1dE51bWJlcjsgYysrKSB7XG4gICAgICAgIGNhbGNTdHIgKz0gYFxuICAgICAgICAgICAgbGV0IGIke2N9X2RhdGEgPSAke2IuZ2V0QnlJbmRpY2VzKGAke2IudHlwZS5pbmRpY2VzfShjb2xfaW5kZXgsIGJsb2NrLCB3b3JkKWApfTtcbiAgICAgICAgICAgIGNvbF9pbmRleCArPSAxO2A7XG4gICAgICB9XG4gICAgICBjYWxjU3RyICs9IGBcbiAgICAgICAgICAgIHZhciBiX3ZhbHVlOiB1MzI7XG4gICAgICAgICAgICBsZXQgYl9tYXNrOiB1MzIgPSAweDBGMEYwRjBGdTtcbiAgICAgICAgICAgIHZhciBiX3ZhbHVlX2xvd2VyOiB2ZWM0PHUzMj47XG4gICAgICAgICAgICB2YXIgYl92YWx1ZV91cHBlcjogdmVjNDx1MzI+O1xuICAgICAgICAgICAgdmFyIGJfcXVhbnRpemVkX3ZhbHVlczogJHtxRHFEYXRhVHlwZX07XG4gICAgICAgICAgICB2YXIgYl9kZXF1YW50aXplZF92YWx1ZXM6ICR7cURxRGF0YVR5cGV9O2A7XG4gICAgICByZXR1cm4gY2FsY1N0cjtcbiAgICB9O1xuICAgIHJldHVybiBgXG4gICAgICAgIHZhcjx3b3JrZ3JvdXA+IHdvcmtncm91cF9zaGFyZWQ6IGFycmF5PCR7b3V0cHV0LnR5cGUudmFsdWV9LCAke291dHB1dE51bWJlciAqIHdvcmtncm91cFNpemV9PjtcbiAgICAgICAgJHtzaGFkZXJIZWxwZXIuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcmlhYmxlcywgb3V0cHV0KX1cbiAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KFt3b3JrZ3JvdXBTaXplLCAxLCAxXSl9XG4gICAgICAgICAgbGV0IG91dHB1dF9pbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKGAoZ2xvYmFsX2lkeCAvICR7d29ya2dyb3VwU2l6ZX0pICogJHtvdXRwdXROdW1iZXJ9YCl9O1xuICAgICAgICAgIGxldCBjb2wgPSBvdXRwdXRfaW5kaWNlc1syXTtcbiAgICAgICAgICBsZXQgcm93ID0gb3V0cHV0X2luZGljZXNbMV07XG4gICAgICAgICAgbGV0IGJhdGNoID0gb3V0cHV0X2luZGljZXNbMF07XG4gICAgICAgICAgbGV0IG5CbG9ja3NQZXJDb2wgPSB1bmlmb3Jtcy5iX3NoYXBlWzFdO1xuXG4gICAgICAgICAgZm9yICh2YXIgYmxvY2sgPSBsb2NhbF9pZC54OyBibG9jayA8IG5CbG9ja3NQZXJDb2w7IGJsb2NrICs9ICR7d29ya2dyb3VwU2l6ZX0pIHtcbiAgICAgICAgICAgIC8vcHJvY2VzcyBvbmUgYmxvY2tcbiAgICAgICAgICAgIHZhciB3b3JkX29mZnNldDogdTMyID0gYmxvY2sgKiAke2F0dHJpYnV0ZXMuYmxvY2tTaXplIC8gYUNvbXBvbmVudHN9O1xuICAgICAgICAgICAgJHtwcmVwYXJlU2NhbGVBbmRaZXJvUG9pbnQoKX1cbiAgICAgICAgICAgIGZvciAodmFyIHdvcmQ6IHUzMiA9IDA7IHdvcmQgPCAke2Jsb2JTaXplSW5Xb3Jkc307IHdvcmQgKz0gJHtiQ29tcG9uZW50c30pIHtcbiAgICAgICAgICAgICAgJHtwcmVwYXJlQkRhdGEoKX1cbiAgICAgICAgICAgICAgZm9yICh2YXIgaTogdTMyID0gMDsgaSA8ICR7YkNvbXBvbmVudHN9OyBpKyspIHtcbiAgICAgICAgICAgICAgICAke3Byb2Nlc3NPbmVXb3JkKCl9XG4gICAgICAgICAgICAgICAgd29yZF9vZmZzZXQgKz0gJHs4IC8gYUNvbXBvbmVudHN9O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgICAgIGlmIChsb2NhbF9pZC54IDwgJHtvdXRwdXROdW1iZXJ9KSB7XG4gICAgICAgICAgICB2YXIgb3V0cHV0X3ZhbHVlOiAke291dHB1dC50eXBlLnZhbHVlfSA9ICR7b3V0cHV0LnR5cGUudmFsdWV9KDApO1xuICAgICAgICAgICAgdmFyIHdvcmtncm91cF9zaGFyZWRfb2Zmc2V0OiB1MzIgPSBsb2NhbF9pZC54O1xuICAgICAgICAgICAgZm9yICh2YXIgYjogdTMyID0gMHU7IGIgPCAke3dvcmtncm91cFNpemV9dTsgYisrKSB7XG4gICAgICAgICAgICAgIG91dHB1dF92YWx1ZSArPSB3b3JrZ3JvdXBfc2hhcmVkW3dvcmtncm91cF9zaGFyZWRfb2Zmc2V0XTtcbiAgICAgICAgICAgICAgd29ya2dyb3VwX3NoYXJlZF9vZmZzZXQgKz0gJHtvdXRwdXROdW1iZXJ9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJHtvdXRwdXQuc2V0QnlJbmRpY2VzKGAke291dHB1dC50eXBlLmluZGljZXN9KGJhdGNoLCByb3csIGNvbCArIGxvY2FsX2lkLngpYCwgJ291dHB1dF92YWx1ZScpfTtcbiAgICAgICAgICB9XG4gICAgICAgIH1gO1xuICB9O1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdNYXRNdWxOQml0cycsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2F0dHJpYnV0ZXMuYmxvY2tTaXplfTske2F0dHJpYnV0ZXMuYml0c307JHthQ29tcG9uZW50c307JHtiQ29tcG9uZW50c307JHtjb21wb25lbnRzfTske291dHB1dE51bWJlcn07JHt3b3JrZ3JvdXBTaXplfWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llczogQXJyYXkoaW5wdXRzLmxlbmd0aCkuZmlsbCgncmFuaycpLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogZGlzcGF0Y2hTaXplIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuLy8gQ3VycmVudGx5LCBvbmx5IHN1cHBvcnQgYmxvY2tTaXplID0gMzIuXG5leHBvcnQgY29uc3QgY3JlYXRlTWF0TXVsTkJpdHNCbG9ja1NpemUzMlByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogTWF0TXVsTkJpdHNBdHRyaWJ1dGVzLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGFSYW5rID0gaW5wdXRTaGFwZS5sZW5ndGg7XG4gIGNvbnN0IGRpbUFPdXRlciA9IGlucHV0U2hhcGVbYVJhbmsgLSAyXTtcbiAgY29uc3QgZGltSW5uZXIgPSBhdHRyaWJ1dGVzLms7XG4gIGNvbnN0IGRpbUJPdXRlciA9IGF0dHJpYnV0ZXMubjtcbiAgY29uc3QgYmF0Y2hEaW1zID0gaW5wdXRTaGFwZS5zbGljZSgwLCBhUmFuayAtIDIpO1xuICBjb25zdCBiYXRjaFNpemUgPSBTaGFwZVV0aWwuc2l6ZShiYXRjaERpbXMpO1xuICBjb25zdCBibG9iU2l6ZSA9IGlucHV0c1sxXS5kaW1zWzJdO1xuICBjb25zdCBibG9iU2l6ZUluV29yZHMgPSBibG9iU2l6ZSAvIDQ7XG4gIGNvbnN0IGRhdGFUeXBlID0gaW5wdXRzWzBdLmRhdGFUeXBlO1xuICBjb25zdCBhQ29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoYXR0cmlidXRlcy5rKTtcbiAgY29uc3QgYkNvbXBvbmVudHMgPSBnZXRNYXhDb21wb25lbnRzKGJsb2JTaXplSW5Xb3Jkcyk7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gYmF0Y2hEaW1zLmNvbmNhdChbZGltQU91dGVyLCBkaW1CT3V0ZXJdKTtcblxuICBjb25zdCB3b3JrZ3JvdXBTaXplID0gMTI4O1xuICBjb25zdCB3b3JrZ3JvdXBZID0gZGltQk91dGVyICUgOCA9PT0gMCA/IDggOiBkaW1CT3V0ZXIgJSA0ID09PSAwID8gNCA6IDE7XG4gIGNvbnN0IHdvcmtncm91cFggPSB3b3JrZ3JvdXBTaXplIC8gd29ya2dyb3VwWTtcbiAgY29uc3QgdGlsZVNpemUgPSB3b3JrZ3JvdXBYICogYkNvbXBvbmVudHMgKiA4OyAvLyBlYWNoIHVpbnQzMiBoYXMgOCBkYXRhLlxuICBjb25zdCBhTGVuZ3RoUGVyVGlsZSA9IHRpbGVTaXplIC8gYUNvbXBvbmVudHM7XG4gIGNvbnN0IGJsb2Nrc1BlclRpbGUgPSB0aWxlU2l6ZSAvIGF0dHJpYnV0ZXMuYmxvY2tTaXplO1xuICBjb25zdCBkaXNwYXRjaFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyB3b3JrZ3JvdXBZO1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtdO1xuICBjb25zdCBpbnB1dFNoYXBlVGVtcCA9IFtiYXRjaFNpemUsIGRpbUFPdXRlciwgZGltSW5uZXIgLyBhQ29tcG9uZW50c107XG4gIGNvbnN0IGJTaGFwZSA9IFNoYXBlVXRpbC5jb252ZXJ0U2hhcGUoaW5wdXRzWzFdLmRpbXMpLnNsaWNlKCk7XG4gIGJTaGFwZS5zcGxpY2UoLTEsIDEsIGJsb2JTaXplSW5Xb3JkcyAvIGJDb21wb25lbnRzKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRTaGFwZVRlbXApKTtcbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoYlNoYXBlKSk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1syXS5kaW1zKSk7XG4gIGlmIChpbnB1dHMubGVuZ3RoID09PSA0KSB7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoU2hhcGVVdGlsLmNvbnZlcnRTaGFwZShpbnB1dHNbM10uZGltcykpKTtcbiAgfVxuICBjb25zdCBvdXRwdXRTaGFwZVRlbXAgPSBbYmF0Y2hTaXplLCBkaW1BT3V0ZXIsIGRpbUJPdXRlcl07XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKG91dHB1dFNoYXBlVGVtcCkpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IGlucHV0UmFuayA9IGlucHV0U2hhcGVUZW1wLmxlbmd0aDtcbiAgICBjb25zdCBhID0gaW5wdXRWYXJpYWJsZSgnYScsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRSYW5rLCBhQ29tcG9uZW50cyk7XG4gICAgY29uc3QgYiA9IGlucHV0VmFyaWFibGUoJ2InLCBEYXRhVHlwZS51aW50MzIsIGJTaGFwZS5sZW5ndGgsIGJDb21wb25lbnRzKTtcbiAgICBjb25zdCBzY2FsZXMgPSBpbnB1dFZhcmlhYmxlKCdzY2FsZXMnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgaW5wdXRWYXJpYWJsZXMgPSBbYSwgYiwgc2NhbGVzXTtcbiAgICBjb25zdCB6ZXJvUG9pbnRzID1cbiAgICAgIGlucHV0cy5sZW5ndGggPT09IDQgPyBpbnB1dFZhcmlhYmxlKCd6ZXJvX3BvaW50cycsIERhdGFUeXBlLnVpbnQzMiwgaW5wdXRzWzNdLmRpbXMubGVuZ3RoKSA6IHVuZGVmaW5lZDtcbiAgICBpZiAoemVyb1BvaW50cykge1xuICAgICAgaW5wdXRWYXJpYWJsZXMucHVzaCh6ZXJvUG9pbnRzKTtcbiAgICB9XG4gICAgY29uc3Qgb3V0cHV0UmFuayA9IG91dHB1dFNoYXBlVGVtcC5sZW5ndGg7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0UmFuayk7XG4gICAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUoaW5wdXRzWzBdLmRhdGFUeXBlKTtcbiAgICBjb25zdCByZWFkQSA9ICgpID0+IHtcbiAgICAgIHN3aXRjaCAoYUNvbXBvbmVudHMpIHtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgbGV0IGFfZGF0YTAgPSB2ZWM0PCR7ZGF0YVR5cGV9PihzdWJfYVt3b3JkX29mZnNldF0sIHN1Yl9hW3dvcmRfb2Zmc2V0ICsgMV0sIHN1Yl9hW3dvcmRfb2Zmc2V0ICsgMl0sIHN1Yl9hW3dvcmRfb2Zmc2V0ICsgM10pO1xuICAgICAgICAgIGxldCBhX2RhdGExID0gdmVjNDwke2RhdGFUeXBlfT4oc3ViX2Fbd29yZF9vZmZzZXQgKyA0XSwgc3ViX2Fbd29yZF9vZmZzZXQgKyA1XSwgc3ViX2Fbd29yZF9vZmZzZXQgKyA2XSwgc3ViX2Fbd29yZF9vZmZzZXQgKyA3XSk7YDtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgbGV0IGFfZGF0YTAgPSB2ZWM0PCR7ZGF0YVR5cGV9PihzdWJfYVt3b3JkX29mZnNldF0sIHN1Yl9hW3dvcmRfb2Zmc2V0ICsgMV0pO1xuICAgICAgICAgIGxldCBhX2RhdGExID0gdmVjNDwke2RhdGFUeXBlfT4oc3ViX2Fbd29yZF9vZmZzZXQgKyAyXSwgc3ViX2Fbd29yZF9vZmZzZXQgKyAzXSk7YDtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgbGV0IGFfZGF0YTAgPSBzdWJfYVt3b3JkX29mZnNldF07XG4gICAgICAgICAgbGV0IGFfZGF0YTEgPSBzdWJfYVt3b3JkX29mZnNldCArIDFdO2A7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2FDb21wb25lbnRzfS1jb21wb25lbnQgaXMgbm90IHN1cHBvcnRlZC5gKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIGBcbiAgICAgICAgdmFyPHdvcmtncm91cD4gc3ViX2E6IGFycmF5PCR7YS50eXBlLnZhbHVlfSwgJHthTGVuZ3RoUGVyVGlsZX0+O1xuICAgICAgICB2YXI8d29ya2dyb3VwPiBpbnRlcl9yZXN1bHRzOiBhcnJheTxhcnJheTwke291dHB1dC50eXBlLnZhbHVlfSwgJHt3b3JrZ3JvdXBYfT4sICR7d29ya2dyb3VwWX0+O1xuICAgICAgICAke3NoYWRlckhlbHBlci5kZWNsYXJlVmFyaWFibGVzKC4uLmlucHV0VmFyaWFibGVzLCBvdXRwdXQpfVxuICAgICAgICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoW3dvcmtncm91cFgsIHdvcmtncm91cFksIDFdKX1cbiAgICAgICAgICBsZXQgb3V0cHV0X2luZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoYHdvcmtncm91cF9pbmRleCAqICR7d29ya2dyb3VwWX1gKX07XG4gICAgICAgICAgbGV0IGNvbCA9IG91dHB1dF9pbmRpY2VzWzJdO1xuICAgICAgICAgIGxldCByb3cgPSBvdXRwdXRfaW5kaWNlc1sxXTtcbiAgICAgICAgICBsZXQgYmF0Y2ggPSBvdXRwdXRfaW5kaWNlc1swXTtcbiAgICAgICAgICBsZXQgbl9ibG9ja3NfcGVyX2NvbCA9IHVuaWZvcm1zLmJfc2hhcGVbMV07XG4gICAgICAgICAgbGV0IG51bV90aWxlcyA9ICAobl9ibG9ja3NfcGVyX2NvbCAtIDEpIC8gJHtibG9ja3NQZXJUaWxlfSArIDE7XG5cbiAgICAgICAgICAvLyBMb29wIG92ZXIgc2hhcmVkIGRpbWVuc2lvbi5cbiAgICAgICAgICBmb3IgKHZhciB0aWxlOiB1MzIgPSAwOyB0aWxlIDwgbnVtX3RpbGVzOyB0aWxlICs9IDEpIHtcbiAgICAgICAgICAgIGxldCBhX2NvbF9zdGFydCA9IHRpbGUgKiAke2FMZW5ndGhQZXJUaWxlfTtcbiAgICAgICAgICAgIC8vIGxvYWQgb25lIHRpbGUgQSBkYXRhIGludG8gc2hhcmVkIG1lbW9yeS5cbiAgICAgICAgICAgIGZvciAodmFyIGFfb2Zmc2V0ID0gbG9jYWxfaWR4OyBhX29mZnNldCA8ICR7YUxlbmd0aFBlclRpbGV9OyBhX29mZnNldCArPSAke3dvcmtncm91cFNpemV9KVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBsZXQgYV9jb2wgPSBhX2NvbF9zdGFydCArIGFfb2Zmc2V0O1xuICAgICAgICAgICAgICBpZiAoYV9jb2wgPCB1bmlmb3Jtcy5hX3NoYXBlWzJdKVxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgc3ViX2FbYV9vZmZzZXRdID0gJHthLmdldEJ5SW5kaWNlcyhgJHthLnR5cGUuaW5kaWNlc30oYmF0Y2gsIHJvdywgYV9jb2wpYCl9O1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1Yl9hW2Ffb2Zmc2V0XSA9ICR7YS50eXBlLnZhbHVlfSgwKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuXG4gICAgICAgICAgICAvLyBlYWNoIHRocmVhZCBwcm9jZXNzIG9uZSBibG9ja1xuICAgICAgICAgICAgbGV0IGJfcm93ID0gY29sICsgbG9jYWxfaWQueTtcbiAgICAgICAgICAgIGxldCBibG9jayA9IHRpbGUgKiAke2Jsb2Nrc1BlclRpbGV9ICsgbG9jYWxfaWQueDtcbiAgICAgICAgICAgICR7XG4gICAgICAgICAgICAgIHplcm9Qb2ludHNcbiAgICAgICAgICAgICAgICA/IGBcbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X2J5dGVzX3Blcl9jb2wgPSAobl9ibG9ja3NfcGVyX2NvbCArIDEpIC8gMjtcbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X2J5dGVfY291bnQgPSBiX3JvdyAqIHplcm9fcG9pbnRfYnl0ZXNfcGVyX2NvbCArIChibG9jayA+PiAweDF1KTtcbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X3dvcmRfaW5kZXggPSB6ZXJvX3BvaW50X2J5dGVfY291bnQgPj4gMHgydTtcbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X2J5dGVfb2Zmc2V0ID0gemVyb19wb2ludF9ieXRlX2NvdW50ICYgMHgzdTtcbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X25pYmJsZV9vZmZzZXQ6IHUzMiA9IGJsb2NrICYgMHgxdTtcbiAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X2JpdHNfb2Zmc2V0ID0gKHplcm9fcG9pbnRfYnl0ZV9vZmZzZXQgPDwgMykgKyAoemVyb19wb2ludF9uaWJibGVfb2Zmc2V0IDw8IDIpO1xuICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfd29yZCA9ICR7emVyb1BvaW50cy5nZXRCeU9mZnNldCgnemVyb19wb2ludF93b3JkX2luZGV4Jyl9ID4+IHplcm9fcG9pbnRfYml0c19vZmZzZXQ7XG4gICAgICAgICAgICBsZXQgemVyb19wb2ludCA9ICR7ZGF0YVR5cGV9KCh6ZXJvX3BvaW50X3dvcmQpICYgMHhGdSk7YFxuICAgICAgICAgICAgICAgIDogYFxuICAgICAgICAgICAgLy8gVGhlIGRlZmF1bHQgemVybyBwb2ludCBpcyA4IGZvciB1bnNpZ25lZCA0LWJpdCBxdWFudGl6YXRpb24uXG4gICAgICAgICAgICBsZXQgemVyb19wb2ludCA9ICR7ZGF0YVR5cGV9KCR7OC4wfSk7YFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHNjYWxlID0gJHtzY2FsZXMuZ2V0QnlPZmZzZXQoYGJfcm93ICogbl9ibG9ja3NfcGVyX2NvbCArIGJsb2NrYCl9O1xuICAgICAgICAgICAgbGV0IGJfZGF0YSA9ICR7Yi5nZXRCeUluZGljZXMoYCR7Yi50eXBlLmluZGljZXN9KGJfcm93LCBibG9jaywgMClgKX07XG4gICAgICAgICAgICB2YXIgd29yZF9vZmZzZXQgPSBsb2NhbF9pZC54ICogJHthdHRyaWJ1dGVzLmJsb2NrU2l6ZSAvIGFDb21wb25lbnRzfTtcbiAgICAgICAgICAgIGZvciAodmFyIGk6IHUzMiA9IDA7IGkgPCAke2JDb21wb25lbnRzfTsgaSsrKSB7XG4gICAgICAgICAgICAgICR7cmVhZEEoKX1cbiAgICAgICAgICAgICAgbGV0IGJfdmFsdWUgPSAke2JDb21wb25lbnRzID09PSAxID8gYGJfZGF0YWAgOiBgYl9kYXRhW2ldYH07XG4gICAgICAgICAgICAgIGxldCBiX3ZhbHVlX2xvd2VyID0gdW5wYWNrNHhVOChiX3ZhbHVlICYgMHgwRjBGMEYwRnUpO1xuICAgICAgICAgICAgICBsZXQgYl92YWx1ZV91cHBlciA9IHVucGFjazR4VTgoKGJfdmFsdWUgPj4gNCkgJiAweDBGMEYwRjBGdSk7XG4gICAgICAgICAgICAgIGxldCBiX3F1YW50aXplZF92YWx1ZXMgPSBtYXQyeDQ8JHtkYXRhVHlwZX0+KCR7QXJyYXkuZnJvbShcbiAgICAgICAgICAgICAgICB7IGxlbmd0aDogNCB9LFxuICAgICAgICAgICAgICAgIChfLCBpKSA9PiBgJHtkYXRhVHlwZX0oYl92YWx1ZV9sb3dlclske2l9XSksICR7ZGF0YVR5cGV9KGJfdmFsdWVfdXBwZXJbJHtpfV0pYCxcbiAgICAgICAgICAgICAgKS5qb2luKCcsICcpfSk7XG4gICAgICAgICAgICAgIGxldCBiX2RlcXVhbnRpemVkX3ZhbHVlcyA9IChiX3F1YW50aXplZF92YWx1ZXMgLSBtYXQyeDQ8JHtkYXRhVHlwZX0+KCR7QXJyYXkoOCkuZmlsbCgnemVyb19wb2ludCcpLmpvaW4oJywnKX0pKSAqIHNjYWxlO1xuICAgICAgICAgICAgICBpbnRlcl9yZXN1bHRzW2xvY2FsX2lkLnldW2xvY2FsX2lkLnhdICs9ICR7QXJyYXkuZnJvbShcbiAgICAgICAgICAgICAgICB7IGxlbmd0aDogMiB9LFxuICAgICAgICAgICAgICAgIChfLCBpKSA9PiBgJHtgZG90KGFfZGF0YSR7aX0sIGJfZGVxdWFudGl6ZWRfdmFsdWVzWyR7aX1dKWB9YCxcbiAgICAgICAgICAgICAgKS5qb2luKCcgKyAnKX07XG4gICAgICAgICAgICAgIHdvcmRfb2Zmc2V0ICs9ICR7OCAvIGFDb21wb25lbnRzfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAobG9jYWxfaWR4IDwgJHt3b3JrZ3JvdXBZfSkge1xuICAgICAgICAgICAgdmFyIG91dHB1dF92YWx1ZTogJHtvdXRwdXQudHlwZS52YWx1ZX0gPSAke291dHB1dC50eXBlLnZhbHVlfSgwKTtcbiAgICAgICAgICAgIGZvciAodmFyIGIgPSAwdTsgYiA8ICR7d29ya2dyb3VwWH07IGIrKykge1xuICAgICAgICAgICAgICBvdXRwdXRfdmFsdWUgKz0gaW50ZXJfcmVzdWx0c1tsb2NhbF9pZHhdW2JdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbCArIGxvY2FsX2lkeCA8IHVuaWZvcm1zLm91dHB1dF9zaGFwZVsyXSlcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgJHtvdXRwdXQuc2V0QnlJbmRpY2VzKGAke291dHB1dC50eXBlLmluZGljZXN9KGJhdGNoLCByb3csIGNvbCArIGxvY2FsX2lkeClgLCAnb3V0cHV0X3ZhbHVlJyl9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9YDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnQmxvY2t3aXNlTWF0TXVsTkJpdHMzMicsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2F0dHJpYnV0ZXMuYmxvY2tTaXplfTske2FDb21wb25lbnRzfTske2JDb21wb25lbnRzfTske3dvcmtncm91cFh9OyR7d29ya2dyb3VwWX1gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IEFycmF5KGlucHV0cy5sZW5ndGgpLmZpbGwoJ3JhbmsnKSxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGUgfV0sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IGRpc3BhdGNoU2l6ZSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBtYXRNdWxOQml0cyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogTWF0TXVsTkJpdHNBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgaWYgKFxuICAgIGF0dHJpYnV0ZXMuYmxvY2tTaXplID09PSAzMiAmJlxuICAgIGNvbnRleHQuYWRhcHRlckluZm8uaXNWZW5kb3IoJ2ludGVsJykgJiZcbiAgICBjb250ZXh0LmFkYXB0ZXJJbmZvLmlzQXJjaGl0ZWN0dXJlKCdnZW4tMTJscCcpXG4gICkge1xuICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVNYXRNdWxOQml0c0Jsb2NrU2l6ZTMyUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpKTtcbiAgfSBlbHNlIHtcbiAgICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlTWF0TXVsTkJpdHNQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcykpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VNYXRNdWxOQml0c0F0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBNYXRNdWxOQml0c0F0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KGF0dHJpYnV0ZXMgYXMgT21pdDxNYXRNdWxOQml0c0F0dHJpYnV0ZXMsIGtleW9mIEF0dHJpYnV0ZVdpdGhDYWNoZUtleT4pO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgZ2V0RWxlbWVudEF0LFxuICBJbmRpY2VzSGVscGVyLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICBVbmlmb3JtRGF0YUVsZW1lbnRUeXBlLFxuICBVbmlmb3Jtc0FycmF5VHlwZSxcbn0gZnJvbSAnLi9jb21tb24nO1xuXG5pbnRlcmZhY2UgUGFkQXR0cmlidXRlcyB7XG4gIC8vIDAtY29uc3RhbnQsIDEtcmVmbGVjdCwgMi1lZGdlLCAzLXdyYXBcbiAgcmVhZG9ubHkgbW9kZTogbnVtYmVyO1xuICByZWFkb25seSB2YWx1ZTogbnVtYmVyO1xuICByZWFkb25seSBwYWRzOiBudW1iZXJbXTtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCA8IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RvbyBmZXcgaW5wdXRzJyk7XG4gIH1cbiAgaWYgKGlucHV0c1swXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuZmxvYXQgJiYgaW5wdXRzWzBdLmRhdGFUeXBlICE9PSBEYXRhVHlwZS5mbG9hdDE2KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCB0eXBlIG11c3QgYmUgZmxvYXQgb3IgZmxvYXQxNi4nKTtcbiAgfVxuXG4gIGlmIChpbnB1dHMubGVuZ3RoID49IDIpIHtcbiAgICBsZXQgdmFsaWRQYWRzID0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoICogMiA9PT0gaW5wdXRzWzFdLmRpbXNbMF07XG4gICAgaWYgKGlucHV0cy5sZW5ndGggPT09IDQpIHtcbiAgICAgIHZhbGlkUGFkcyA9IGlucHV0c1szXS5kaW1zWzBdICogMiA9PT0gaW5wdXRzWzFdLmRpbXNbMF07XG4gICAgfVxuICAgIGlmICghdmFsaWRQYWRzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBwYWRzIHNob3VsZCBiZSBhIDFEIHRlbnNvciBvZiBzaGFwZSBbMiAqIGlucHV0X3JhbmtdIG9yIFsyICogbnVtX2F4ZXNdLicpO1xuICAgIH1cbiAgfVxufTtcblxuY29uc3QgZ2V0UGFkQ29uc3RhbnQgPSAob3V0cHV0OiBJbmRpY2VzSGVscGVyLCBpbnB1dFJhbms6IG51bWJlciwgcGFkc0xlbmd0aDogbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgbGV0IGJsb2NrID0gJyc7XG4gIGZvciAobGV0IGkgPSBpbnB1dFJhbmsgLSAxOyBpID49IDA7IC0taSkge1xuICAgIGJsb2NrICs9IGBcbiAgICAgICAgICAgIGsgPSBpMzIoJHtvdXRwdXQuaW5kaWNlc0dldCgnaW5kaWNlcycsIGkpfSkgLSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMucGFkcycsIGksIHBhZHNMZW5ndGgpfTtcbiAgICAgICAgICAgIGlmIChrIDwgMCkge1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChrID49IGkzMigke2dldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIGksIGlucHV0UmFuayl9KSkge1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9mZnNldCArPSBrICogaTMyKCR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3N0cmlkZXMnLCBpLCBpbnB1dFJhbmspfSk7XG4gICAgICAgIGA7XG4gIH1cblxuICByZXR1cm4gYFxuICAgICAgICAgIHZhbHVlID0gJHtvdXRwdXQudHlwZS52YWx1ZX0odW5pZm9ybXMuY29uc3RhbnRfdmFsdWUpO1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMTsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgb2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIHZhciBrID0gMDtcbiAgICAgICAgICAgICR7YmxvY2t9XG4gICAgICAgICAgICB2YWx1ZSA9IHhbb2Zmc2V0XTtcbiAgICAgICAgICB9XG4gICAgICBgO1xufTtcblxuY29uc3QgZ2V0UGFkUmVmbGVjdCA9IChvdXRwdXQ6IEluZGljZXNIZWxwZXIsIGlucHV0UmFuazogbnVtYmVyLCBwYWRzTGVuZ3RoOiBudW1iZXIpOiBzdHJpbmcgPT4ge1xuICBsZXQgYmxvY2sgPSAnJztcbiAgZm9yIChsZXQgaSA9IGlucHV0UmFuayAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgYmxvY2sgKz0gYFxuICAgICAgICAgICAgICAgIGsgPSBpMzIoJHtvdXRwdXQuaW5kaWNlc0dldCgnaW5kaWNlcycsIGkpfSkgLSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMucGFkcycsIGksIHBhZHNMZW5ndGgpfTtcbiAgICAgICAgICAgICAgICBpZiAoayA8IDApIHtcbiAgICAgICAgICAgICAgICAgIGsgPSAtaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgbGV0IF8ybl8xID0gMiAqIChpMzIoJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCBpLCBpbnB1dFJhbmspfSkgLSAxKTtcbiAgICAgICAgICAgICAgICAgIGsgPSBrICUgXzJuXzE7XG4gICAgICAgICAgICAgICAgICBpZihrID49IGkzMigke2dldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIGksIGlucHV0UmFuayl9KSkge1xuICAgICAgICAgICAgICAgICAgICBrID0gXzJuXzEgLSBrO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gayAqIGkzMigke2dldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zdHJpZGVzJywgaSwgaW5wdXRSYW5rKX0pO1xuICAgICAgICAgICAgYDtcbiAgfVxuXG4gIHJldHVybiBgXG4gICAgICAgICAgICAgIHZhciBvZmZzZXQgPSAwO1xuICAgICAgICAgICAgICB2YXIgayA9IDA7XG4gICAgICAgICAgICAgICR7YmxvY2t9XG4gICAgICAgICAgICAgIHZhbHVlID0geFtvZmZzZXRdO1xuICAgICAgICAgIGA7XG59O1xuXG5jb25zdCBnZXRQYWRFZGdlID0gKG91dHB1dDogSW5kaWNlc0hlbHBlciwgaW5wdXRSYW5rOiBudW1iZXIsIHBhZHNMZW5ndGg6IG51bWJlcik6IHN0cmluZyA9PiB7XG4gIGxldCBibG9jayA9ICcnO1xuICBmb3IgKGxldCBpID0gaW5wdXRSYW5rIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICBibG9jayArPSBgXG4gICAgICAgICAgICAgICAgayA9IGkzMigke291dHB1dC5pbmRpY2VzR2V0KCdpbmRpY2VzJywgaSl9KSAtICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5wYWRzJywgaSwgcGFkc0xlbmd0aCl9O1xuICAgICAgICAgICAgICAgIGlmIChrIDwgMCkge1xuICAgICAgICAgICAgICAgICAgayA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChrID49IGkzMigke2dldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIGksIGlucHV0UmFuayl9KSkge1xuICAgICAgICAgICAgICAgICAgayA9IGkzMigke2dldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zaGFwZScsIGksIGlucHV0UmFuayl9KSAtIDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG9mZnNldCArPSBrICogaTMyKCR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3N0cmlkZXMnLCBpLCBpbnB1dFJhbmspfSk7XG4gICAgICAgICAgICBgO1xuICB9XG5cbiAgcmV0dXJuIGBcbiAgICAgICAgICAgICAgdmFyIG9mZnNldCA9IDA7XG4gICAgICAgICAgICAgIHZhciBrID0gMDtcbiAgICAgICAgICAgICAgJHtibG9ja31cbiAgICAgICAgICAgICAgdmFsdWUgPSB4W29mZnNldF07XG4gICAgICAgICAgYDtcbn07XG5cbmNvbnN0IGdldFBhZFdyYXAgPSAob3V0cHV0OiBJbmRpY2VzSGVscGVyLCBpbnB1dFJhbms6IG51bWJlciwgcGFkc0xlbmd0aDogbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgbGV0IGJsb2NrID0gJyc7XG4gIGZvciAobGV0IGkgPSBpbnB1dFJhbmsgLSAxOyBpID49IDA7IC0taSkge1xuICAgIGJsb2NrICs9IGBcbiAgICAgICAgICAgICAgICBrID0gaTMyKCR7b3V0cHV0LmluZGljZXNHZXQoJ2luZGljZXMnLCBpKX0pIC0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnBhZHMnLCBpLCBwYWRzTGVuZ3RoKX07XG4gICAgICAgICAgICAgICAgaWYgKGsgPCAwKSAge1xuICAgICAgICAgICAgICAgICAgayArPSBpMzIoJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCBpLCBpbnB1dFJhbmspfV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoayA+PSBpMzIoJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnhfc2hhcGUnLCBpLCBpbnB1dFJhbmspfSkpIHtcbiAgICAgICAgICAgICAgICAgIGsgLT0gaTMyKCR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy54X3NoYXBlJywgaSwgaW5wdXRSYW5rKX0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gayAqIGkzMigke2dldEVsZW1lbnRBdCgndW5pZm9ybXMueF9zdHJpZGVzJywgaSwgaW5wdXRSYW5rKX0pO1xuICAgICAgICAgICAgYDtcbiAgfVxuXG4gIHJldHVybiBgXG4gICAgICAgICAgICAgIHZhciBvZmZzZXQgPSAwO1xuICAgICAgICAgICAgICB2YXIgayA9IDA7XG4gICAgICAgICAgICAgICR7YmxvY2t9XG4gICAgICAgICAgICAgIHZhbHVlID0geFtvZmZzZXRdO1xuICAgICAgICAgIGA7XG59O1xuXG5jb25zdCBnZXRQYWRTbmlwcGV0ID0gKG91dHB1dDogSW5kaWNlc0hlbHBlciwgaW5wdXRSYW5rOiBudW1iZXIsIGF0dHJpYnV0ZXM6IFBhZEF0dHJpYnV0ZXMpOiBzdHJpbmcgPT4ge1xuICBzd2l0Y2ggKGF0dHJpYnV0ZXMubW9kZSkge1xuICAgIGNhc2UgMDpcbiAgICAgIHJldHVybiBnZXRQYWRDb25zdGFudChvdXRwdXQsIGlucHV0UmFuaywgYXR0cmlidXRlcy5wYWRzLmxlbmd0aCk7XG4gICAgY2FzZSAxOlxuICAgICAgcmV0dXJuIGdldFBhZFJlZmxlY3Qob3V0cHV0LCBpbnB1dFJhbmssIGF0dHJpYnV0ZXMucGFkcy5sZW5ndGgpO1xuICAgIGNhc2UgMjpcbiAgICAgIHJldHVybiBnZXRQYWRFZGdlKG91dHB1dCwgaW5wdXRSYW5rLCBhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoKTtcbiAgICBjYXNlIDM6XG4gICAgICByZXR1cm4gZ2V0UGFkV3JhcChvdXRwdXQsIGlucHV0UmFuaywgYXR0cmlidXRlcy5wYWRzLmxlbmd0aCk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBtb2RlJyk7XG4gIH1cbn07XG5cbmNvbnN0IGNyZWF0ZVBhZFByb2dyYW1JbmZvID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBQYWRBdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IFNoYXBlVXRpbC5wYWRTaGFwZShpbnB1dHNbMF0uZGltcy5zbGljZSgpLCBhdHRyaWJ1dGVzLnBhZHMpO1xuICBjb25zdCBpbnB1dERpbXMgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogYXR0cmlidXRlcy5wYWRzIH0sXG4gIF07XG5cbiAgY29uc3QgaXNWYWx1ZUZyb21JbnB1dCA9IGlucHV0cy5sZW5ndGggPj0gMyAmJiBpbnB1dHNbMl0uZGF0YTtcbiAgaWYgKGF0dHJpYnV0ZXMubW9kZSA9PT0gMCkge1xuICAgIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKHsgdHlwZTogaXNWYWx1ZUZyb21JbnB1dCA/IGlucHV0c1syXS5kYXRhVHlwZSA6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBhdHRyaWJ1dGVzLnZhbHVlIH0pO1xuICB9XG5cbiAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzBdLmRpbXMsIG91dHB1dFNoYXBlKSk7XG4gIGNvbnN0IGlucHV0RGVwZW5kZW5jaWVzOiBQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeVtdID0gWydyYW5rJ107XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoKTtcbiAgICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ3gnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0RGltcy5sZW5ndGgpO1xuICAgIGNvbnN0IGRhdGFUeXBlID0gaW5wdXQudHlwZS52YWx1ZTtcbiAgICBjb25zdCBwYWRTbmlwcGV0ID0gZ2V0UGFkU25pcHBldChvdXRwdXQsIGlucHV0RGltcy5sZW5ndGgsIGF0dHJpYnV0ZXMpO1xuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ291dHB1dF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3BhZHMnLCB0eXBlOiAnaTMyJywgbGVuZ3RoOiBhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoIH0sXG4gICAgXTtcbiAgICBpZiAoYXR0cmlidXRlcy5tb2RlID09PSAwKSB7XG4gICAgICB1bmlmb3Jtcy5wdXNoKHsgbmFtZTogJ2NvbnN0YW50X3ZhbHVlJywgdHlwZTogKGlzVmFsdWVGcm9tSW5wdXQgPyBkYXRhVHlwZSA6ICdmMzInKSBhcyBVbmlmb3JtRGF0YUVsZW1lbnRUeXBlIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBgXG4gICAgICAgICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBvdXRwdXQpfVxuICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuXG4gICAgICAgICAgICBsZXQgaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcblxuICAgICAgICAgICAgdmFyIHZhbHVlID0gJHtkYXRhVHlwZX0oMCk7XG4gICAgICAgICAgICAke3BhZFNuaXBwZXR9XG4gICAgICAgICAgICBvdXRwdXRbZ2xvYmFsX2lkeF0gPSB2YWx1ZTtcbiAgICAgICAgfWA7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnUGFkJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHthdHRyaWJ1dGVzLm1vZGV9JHtpc1ZhbHVlRnJvbUlucHV0fWAsIGlucHV0RGVwZW5kZW5jaWVzIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwoU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICB9O1xufTtcblxuY29uc3QgY3JlYXRlUGFkQXR0cmlidXRlc0Zyb21JbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IFBhZEF0dHJpYnV0ZXMpOiBQYWRBdHRyaWJ1dGVzID0+IHtcbiAgaWYgKGlucHV0cy5sZW5ndGggPiAxKSB7XG4gICAgY29uc3QgYmlnSW50NjRQYWRzID0gaW5wdXRzWzFdLmdldEJpZ0ludDY0QXJyYXkoKTtcbiAgICBjb25zdCB2YWx1ZSA9XG4gICAgICBpbnB1dHMubGVuZ3RoID49IDMgJiYgaW5wdXRzWzJdLmRhdGFcbiAgICAgICAgPyBpbnB1dHNbMl0uZGF0YVR5cGUgPT09IERhdGFUeXBlLmZsb2F0MTZcbiAgICAgICAgICA/IGlucHV0c1syXS5nZXRVaW50MTZBcnJheSgpWzBdXG4gICAgICAgICAgOiBpbnB1dHNbMl0uZ2V0RmxvYXQzMkFycmF5KClbMF1cbiAgICAgICAgOiAwLjA7XG5cbiAgICBjb25zdCBpbnB1dFJhbmsgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGg7XG4gICAgY29uc3QgdXBkYXRlUGFkcyA9IG5ldyBJbnQzMkFycmF5KDIgKiBpbnB1dFJhbmspLmZpbGwoMCk7XG4gICAgaWYgKGlucHV0cy5sZW5ndGggPj0gNCkge1xuICAgICAgY29uc3QgYXhlcyA9IGlucHV0c1szXS5nZXRCaWdJbnQ2NEFycmF5KCk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdXBkYXRlUGFkc1tOdW1iZXIoYXhlc1tpXSldID0gTnVtYmVyKGJpZ0ludDY0UGFkc1tpXSk7XG4gICAgICAgIHVwZGF0ZVBhZHNbTnVtYmVyKGF4ZXNbaV0pICsgaW5wdXRSYW5rXSA9IE51bWJlcihiaWdJbnQ2NFBhZHNbaSArIGF4ZXMubGVuZ3RoXSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGJpZ0ludDY0UGFkcy5mb3JFYWNoKCh2LCBpKSA9PiAodXBkYXRlUGFkc1tOdW1iZXIoaSldID0gTnVtYmVyKHYpKSk7XG4gICAgfVxuXG4gICAgY29uc3QgcGFkczogbnVtYmVyW10gPSBbXTtcbiAgICB1cGRhdGVQYWRzLmZvckVhY2goKHYpID0+IHBhZHMucHVzaCh2KSk7XG5cbiAgICByZXR1cm4geyBtb2RlOiBhdHRyaWJ1dGVzLm1vZGUsIHZhbHVlLCBwYWRzIH07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZXM7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBwYWQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFBhZEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCB1cGRhdGVkQXR0cmlidXRlcyA9IGNyZWF0ZVBhZEF0dHJpYnV0ZXNGcm9tSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZVBhZFByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzLCB1cGRhdGVkQXR0cmlidXRlcyksIHsgaW5wdXRzOiBbMF0gfSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBlbnYgfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBQb29sQ29udlV0aWwsIFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5IH0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgZ2V0RWxlbWVudEF0LFxuICBJbmRpY2VzSGVscGVyLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICBVbmlmb3Jtc0FycmF5VHlwZSxcbn0gZnJvbSAnLi9jb21tb24nO1xuXG4vLyBUT0RPOiBzdXBwb3J0OlxuLy8gLSBjZWlsX21vZGUgICAgICAgICAgICAgICAgIFwidGVzdF9tYXhwb29sXzJkX2NlaWxcIlxuLy8gLSBzdG9yYWdlX29yZGVyICAgICAgICAgICAgIFwidGVzdF9tYXhwb29sX3dpdGhfYXJnbWF4XzJkX3ByZWNvbXB1dGVkX3N0cmlkZXNcIlxuLy8gLSBbTWF4UG9vbF0gZGlsYXRpb25zICAgICAgIFwidGVzdF9tYXhwb29sXzJkX2RpbGF0aW9uc1wiXG4vLyAtIFtNYXhQb29sXSBvdXRwdXRbMV0gICAgICAgXCJ0ZXN0X21heHBvb2xfd2l0aF9hcmdtYXhfMmRfcHJlY29tcHV0ZWRfcGFkc1wiXG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmIChlbnYud2ViZ3B1LnZhbGlkYXRlSW5wdXRDb250ZW50ICYmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDEpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQb29sIG9wcyByZXF1aXJlcyAxIGlucHV0LicpO1xuICB9XG59O1xuXG5jb25zdCBnZXRBZGp1c3RlZFBvb2xBdHRyaWJ1dGVzQW5kT3V0cHV0U2hhcGUgPSA8QXR0cmlidXRlVHlwZSBleHRlbmRzIEF2ZXJhZ2VQb29sQXR0cmlidXRlcyB8IE1heFBvb2xBdHRyaWJ1dGVzPihcbiAgaW5wdXQ6IFRlbnNvclZpZXcsXG4gIGF0dHJpYnV0ZXM6IEF0dHJpYnV0ZVR5cGUsXG4gIGlzR2xvYmFsT3BlcmF0b3I6IGJvb2xlYW4sXG4pOiBbQXR0cmlidXRlVHlwZSwgbnVtYmVyW11dID0+IHtcbiAgY29uc3QgaXNDaGFubmVsc0xhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuICBjb25zdCBpbnB1dFNoYXBlQXNDaGFubmVsRmlyc3QgPSBpbnB1dC5kaW1zLnNsaWNlKCk7XG4gIGlmIChpc0NoYW5uZWxzTGFzdCkge1xuICAgIGlucHV0U2hhcGVBc0NoYW5uZWxGaXJzdC5zcGxpY2UoMSwgMCwgaW5wdXRTaGFwZUFzQ2hhbm5lbEZpcnN0LnBvcCgpISk7IC8vIE1vdmUgY2hhbm5lbCB0byB0aGUgc2Vjb25kIHBvc2l0aW9uLlxuICB9XG4gIGNvbnN0IGhhc0RpbGF0aW9ucyA9IE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKGF0dHJpYnV0ZXMsICdkaWxhdGlvbnMnKTtcbiAgY29uc3Qga2VybmVsU2hhcGUgPSBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLnNsaWNlKCk7XG4gIGNvbnN0IHN0cmlkZXMgPSBhdHRyaWJ1dGVzLnN0cmlkZXMuc2xpY2UoKTtcbiAgY29uc3QgZGlsYXRpb25zOiBudW1iZXJbXSA9IGhhc0RpbGF0aW9ucyA/IChhdHRyaWJ1dGVzIGFzIE1heFBvb2xBdHRyaWJ1dGVzKS5kaWxhdGlvbnMuc2xpY2UoKSA6IFtdO1xuICBjb25zdCBwYWRzID0gYXR0cmlidXRlcy5wYWRzLnNsaWNlKCk7XG4gIFBvb2xDb252VXRpbC5hZGp1c3RQb29sQXR0cmlidXRlcyhpc0dsb2JhbE9wZXJhdG9yLCBpbnB1dFNoYXBlQXNDaGFubmVsRmlyc3QsIGtlcm5lbFNoYXBlLCBzdHJpZGVzLCBkaWxhdGlvbnMsIHBhZHMpO1xuXG4gIGNvbnN0IG91dHB1dFNoYXBlQXNDaGFubmVsRmlyc3QgPSBQb29sQ29udlV0aWwuY29tcHV0ZVBvb2xPdXRwdXRTaGFwZShcbiAgICBpc0dsb2JhbE9wZXJhdG9yLFxuICAgIGlucHV0U2hhcGVBc0NoYW5uZWxGaXJzdCxcbiAgICBzdHJpZGVzLFxuICAgIGRpbGF0aW9ucyxcbiAgICBrZXJuZWxTaGFwZSxcbiAgICBwYWRzLFxuICAgIGF0dHJpYnV0ZXMuYXV0b1BhZCxcbiAgKTtcblxuICBjb25zdCBuZXdBdHRyaWJ1dGVzID0gT2JqZWN0LmFzc2lnbih7fSwgYXR0cmlidXRlcyk7XG4gIGlmIChoYXNEaWxhdGlvbnMpIHtcbiAgICBPYmplY3QuYXNzaWduKG5ld0F0dHJpYnV0ZXMsIHsga2VybmVsU2hhcGUsIHN0cmlkZXMsIHBhZHMsIGRpbGF0aW9ucywgY2FjaGVLZXk6IGF0dHJpYnV0ZXMuY2FjaGVLZXkgfSk7XG4gIH0gZWxzZSB7XG4gICAgT2JqZWN0LmFzc2lnbihuZXdBdHRyaWJ1dGVzLCB7IGtlcm5lbFNoYXBlLCBzdHJpZGVzLCBwYWRzLCBjYWNoZUtleTogYXR0cmlidXRlcy5jYWNoZUtleSB9KTtcbiAgfVxuICBjb25zdCBvdXRwdXRTaGFwZUFzQ2hhbm5lbExhc3QgPSBvdXRwdXRTaGFwZUFzQ2hhbm5lbEZpcnN0LnNsaWNlKCk7XG4gIG91dHB1dFNoYXBlQXNDaGFubmVsTGFzdC5wdXNoKG91dHB1dFNoYXBlQXNDaGFubmVsTGFzdC5zcGxpY2UoMSwgMSlbMF0pO1xuICByZXR1cm4gW25ld0F0dHJpYnV0ZXMsIGlzQ2hhbm5lbHNMYXN0ID8gb3V0cHV0U2hhcGVBc0NoYW5uZWxMYXN0IDogb3V0cHV0U2hhcGVBc0NoYW5uZWxGaXJzdF07XG59O1xuXG5jb25zdCBnZXRVbmlmb3JtQW5kUGFkSW5mbyA9IDxBdHRyaWJ1dGVUeXBlIGV4dGVuZHMgQXZlcmFnZVBvb2xBdHRyaWJ1dGVzIHwgTWF4UG9vbEF0dHJpYnV0ZXM+KFxuICBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIGF0dHJpYnV0ZXM6IEF0dHJpYnV0ZVR5cGUsXG4pOiBbUHJvZ3JhbVVuaWZvcm1bXSwgVW5pZm9ybXNBcnJheVR5cGUsIGJvb2xlYW4sIGJvb2xlYW4sIGJvb2xlYW5dID0+IHtcbiAgY29uc3QgaXNDaGFubmVsc0xhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICBjb25zdCBrZXJuZWxTaXplID0gU2hhcGVVdGlsLnNpemUoYXR0cmlidXRlcy5rZXJuZWxTaGFwZSk7XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBrZXJuZWxTaXplIH0sXG4gIF07XG4gIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICB7IG5hbWU6ICdvdXRwdXRTaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICB7IG5hbWU6ICdrZXJuZWxTaXplJywgdHlwZTogJ3UzMicgfSxcbiAgXTtcbiAgaWYgKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoIDw9IDIpIHtcbiAgICBjb25zdCBrdyA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGVbYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggLSAxXTtcbiAgICBjb25zdCBzdyA9IGF0dHJpYnV0ZXMuc3RyaWRlc1thdHRyaWJ1dGVzLnN0cmlkZXMubGVuZ3RoIC0gMV07XG4gICAgY29uc3QgcHdTdGFydCA9IGF0dHJpYnV0ZXMucGFkc1thdHRyaWJ1dGVzLnBhZHMubGVuZ3RoIC8gMiAtIDFdO1xuICAgIGNvbnN0IHB3RW5kID0gYXR0cmlidXRlcy5wYWRzW2F0dHJpYnV0ZXMucGFkcy5sZW5ndGggLSAxXTtcbiAgICBjb25zdCBwd1N0YXJ0RW5kTm90WmVybyA9ICEhKHB3U3RhcnQgKyBwd0VuZCk7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goXG4gICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YToga3cgfSxcbiAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBzdyB9LFxuICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHB3U3RhcnQgfSxcbiAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBwd0VuZCB9LFxuICAgICk7XG4gICAgdW5pZm9ybXMucHVzaChcbiAgICAgIHsgbmFtZTogJ2t3JywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3N3JywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ3B3U3RhcnQnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAncHdFbmQnLCB0eXBlOiAndTMyJyB9LFxuICAgICk7XG5cbiAgICBsZXQgcGhTdGFydEVuZE5vdFplcm8gPSBmYWxzZTtcbiAgICBpZiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggPT09IDIpIHtcbiAgICAgIGNvbnN0IGtoID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZVthdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAtIDJdO1xuICAgICAgY29uc3Qgc2ggPSBhdHRyaWJ1dGVzLnN0cmlkZXNbYXR0cmlidXRlcy5zdHJpZGVzLmxlbmd0aCAtIDJdO1xuICAgICAgY29uc3QgcGhTdGFydCA9IGF0dHJpYnV0ZXMucGFkc1thdHRyaWJ1dGVzLnBhZHMubGVuZ3RoIC8gMiAtIDJdO1xuICAgICAgY29uc3QgcGhFbmQgPSBhdHRyaWJ1dGVzLnBhZHNbYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAtIDJdO1xuICAgICAgcGhTdGFydEVuZE5vdFplcm8gPSAhIShwaFN0YXJ0ICsgcGhFbmQpO1xuICAgICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goXG4gICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBraCB9LFxuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogc2ggfSxcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBoU3RhcnQgfSxcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IHBoRW5kIH0sXG4gICAgICApO1xuXG4gICAgICB1bmlmb3Jtcy5wdXNoKFxuICAgICAgICB7IG5hbWU6ICdraCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICAgIHsgbmFtZTogJ3NoJywgdHlwZTogJ3UzMicgfSxcbiAgICAgICAgeyBuYW1lOiAncGhTdGFydCcsIHR5cGU6ICd1MzInIH0sXG4gICAgICAgIHsgbmFtZTogJ3BoRW5kJywgdHlwZTogJ3UzMicgfSxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBbcHJvZ3JhbVVuaWZvcm1zLCB1bmlmb3JtcywgdHJ1ZSwgcHdTdGFydEVuZE5vdFplcm8sIHBoU3RhcnRFbmROb3RaZXJvXTtcbiAgfSBlbHNlIHtcbiAgICBpZiAoaXNDaGFubmVsc0xhc3QpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUG9vbGluZyB3aXRoIGtlcm5lbFNoYXBlLmxlbmd0aCA+IDIgaXMgbm90IHN1cHBvcnRlZCBmb3IgTkhXQyBmb3JtYXQuJyk7XG4gICAgfVxuICAgIGNvbnN0IGtlcm5lbFN0cmlkZXMgPSBTaGFwZVV0aWwuY29tcHV0ZVN0cmlkZXMoYXR0cmlidXRlcy5rZXJuZWxTaGFwZSk7XG4gICAgcHJvZ3JhbVVuaWZvcm1zLnB1c2goXG4gICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YToga2VybmVsU3RyaWRlcyB9LFxuICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGF0dHJpYnV0ZXMucGFkcyB9LFxuICAgICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGF0dHJpYnV0ZXMuc3RyaWRlcyB9LFxuICAgICk7XG4gICAgdW5pZm9ybXMucHVzaChcbiAgICAgIHsgbmFtZTogJ2tlcm5lbFN0cmlkZXMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBrZXJuZWxTdHJpZGVzLmxlbmd0aCB9LFxuICAgICAgeyBuYW1lOiAncGFkcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IGF0dHJpYnV0ZXMucGFkcy5sZW5ndGggfSxcbiAgICAgIHsgbmFtZTogJ3N0cmlkZXMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBhdHRyaWJ1dGVzLnN0cmlkZXMubGVuZ3RoIH0sXG4gICAgKTtcblxuICAgIGNvbnN0IGhhc1BhZHMgPSBhdHRyaWJ1dGVzLnBhZHMucmVkdWNlKChzdW0sIGN1cikgPT4gc3VtICsgY3VyKTtcbiAgICByZXR1cm4gW3Byb2dyYW1Vbmlmb3JtcywgdW5pZm9ybXMsICEhaGFzUGFkcywgZmFsc2UsIGZhbHNlXTtcbiAgfVxufTtcblxuY29uc3QgZ2VuZXJhdGVQb29saW5nQ29kZSA9IDxBdHRyaWJ1dGVUeXBlIGV4dGVuZHMgQXZlcmFnZVBvb2xBdHRyaWJ1dGVzIHwgTWF4UG9vbEF0dHJpYnV0ZXM+KFxuICBzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcixcbiAgeDogSW5kaWNlc0hlbHBlcixcbiAgcmFuazogbnVtYmVyLFxuICBvdXRwdXRTaGFwZVJhbms6IG51bWJlcixcbiAgYXR0cmlidXRlczogQXR0cmlidXRlVHlwZSxcbiAgb3AxOiBzdHJpbmcsXG4gIG9wMjogc3RyaW5nLFxuICBzdGFydDogbnVtYmVyLFxuICB1bmlmb3JtczogVW5pZm9ybXNBcnJheVR5cGUsXG4gIGhhc1BhZHM6IGJvb2xlYW4sXG4gIHB3U3RhcnRFbmROb3RaZXJvOiBib29sZWFuLFxuICBwaFN0YXJ0RW5kTm90WmVybzogYm9vbGVhbixcbik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGlzQ2hhbm5lbHNMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAgY29uc3QgZGF0YVR5cGUgPSB4LnR5cGUudmFsdWU7XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCB4LnR5cGUudGVuc29yLCBvdXRwdXRTaGFwZVJhbmspO1xuXG4gIGlmIChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCA8PSAyKSB7XG4gICAgbGV0IGNvZGVXID0gJyc7XG4gICAgbGV0IGNvZGVIID0gJyc7XG4gICAgbGV0IGNvZGVIRW5kID0gJyc7XG4gICAgY29uc3QgZGltSWR4VyA9IHJhbmsgLSAoaXNDaGFubmVsc0xhc3QgPyAyIDogMSk7XG4gICAgaWYgKHB3U3RhcnRFbmROb3RaZXJvKSB7XG4gICAgICBjb2RlVyA9IGBcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpOiB1MzIgPSAwdTsgaSA8IHVuaWZvcm1zLmt3OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgIHhJbmRpY2VzWyR7ZGltSWR4V31dID0gaW5kaWNlc1ske2RpbUlkeFd9XSAqIHVuaWZvcm1zLnN3IC0gdW5pZm9ybXMucHdTdGFydCArIGk7XG4gICAgICAgICAgICAgICAgICBpZiAoeEluZGljZXNbJHtkaW1JZHhXfV0gPCAwIHx8IHhJbmRpY2VzWyR7ZGltSWR4V31dXG4gICAgICAgICAgICAgICAgICAgICAgPj0gdW5pZm9ybXMueF9zaGFwZVske2RpbUlkeFd9XSkge1xuICAgICAgICAgICAgICAgICAgICBwYWQrKztcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBsZXQgeF92YWwgPSB4WyR7eC5pbmRpY2VzVG9PZmZzZXQoJ3hJbmRpY2VzJyl9XTtcbiAgICAgICAgICAgICAgICAgICR7b3AxfVxuICAgICAgICAgICAgICAgIH1gO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlVyA9IGBcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpOiB1MzIgPSAwdTsgaSA8IHVuaWZvcm1zLmt3OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgIHhJbmRpY2VzWyR7ZGltSWR4V31dID0gaW5kaWNlc1ske2RpbUlkeFd9XSAqIHVuaWZvcm1zLnN3IC0gdW5pZm9ybXMucHdTdGFydCArIGk7XG4gICAgICAgICAgICAgICAgICBsZXQgeF92YWwgPSB4WyR7eC5pbmRpY2VzVG9PZmZzZXQoJ3hJbmRpY2VzJyl9XTtcbiAgICAgICAgICAgICAgICAgICR7b3AxfVxuICAgICAgICAgICAgICAgIH1gO1xuICAgIH1cblxuICAgIGlmIChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCA9PT0gMikge1xuICAgICAgY29uc3QgZGltSWR4SCA9IHJhbmsgLSAoaXNDaGFubmVsc0xhc3QgPyAzIDogMik7XG4gICAgICBpZiAocGhTdGFydEVuZE5vdFplcm8pIHtcbiAgICAgICAgY29kZUggPSBgXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgajogdTMyID0gMHU7IGogPCB1bmlmb3Jtcy5raDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICB4SW5kaWNlc1ske2RpbUlkeEh9XSA9IGluZGljZXNbJHtkaW1JZHhIfV0gKiB1bmlmb3Jtcy5zaCAtIHVuaWZvcm1zLnBoU3RhcnQgKyBqO1xuICAgICAgICAgICAgICAgICAgaWYgKHhJbmRpY2VzWyR7ZGltSWR4SH1dIDwgMCB8fCB4SW5kaWNlc1ske2RpbUlkeEh9XSA+PSB1bmlmb3Jtcy54X3NoYXBlWyR7ZGltSWR4SH1dKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhZCArPSBpMzIodW5pZm9ybXMua3cpO1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgYDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvZGVIID0gYFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGo6IHUzMiA9IDB1OyBqIDwgdW5pZm9ybXMua2g7IGorKykge1xuICAgICAgICAgICAgICAgICAgeEluZGljZXNbJHtkaW1JZHhIfV0gPSBpbmRpY2VzWyR7ZGltSWR4SH1dICogdW5pZm9ybXMuc2ggLSB1bmlmb3Jtcy5waFN0YXJ0ICsgajtcbiAgICAgICAgICAgICAgICBgO1xuICAgICAgfVxuICAgICAgY29kZUhFbmQgPSBgXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGA7XG4gICAgfVxuXG4gICAgY29uc3QgcG9vbGluZ0NvZGUgPSBgXG4gICAgICAgICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKHgsIG91dHB1dCl9XG5cbiAgICAgICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRTaXplJyl9XG5cbiAgICAgICAgICAgICAgbGV0IGluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgICAgICAgICAgIHZhciB4SW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcblxuICAgICAgICAgICAgICB2YXIgdmFsdWUgPSAke2RhdGFUeXBlfSgke3N0YXJ0fSk7XG4gICAgICAgICAgICAgIHZhciBwYWQgPSAwO1xuICAgICAgICAgICAgICAke2NvZGVIfVxuICAgICAgICAgICAgICAke2NvZGVXfVxuICAgICAgICAgICAgICAke2NvZGVIRW5kfVxuICAgICAgICAgICAgICAke29wMn1cblxuICAgICAgICAgICAgICBvdXRwdXRbZ2xvYmFsX2lkeF0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH1gO1xuICAgIHJldHVybiBwb29saW5nQ29kZTtcbiAgfSBlbHNlIHtcbiAgICBpZiAoaXNDaGFubmVsc0xhc3QpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUG9vbGluZyB3aXRoIGtlcm5lbFNoYXBlLmxlbmd0aCA+IDIgaXMgbm90IHN1cHBvcnRlZCBmb3IgTkhXQyBmb3JtYXQuJyk7XG4gICAgfVxuICAgIGNvbnN0IHN0cmlkZXNSYW5rID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGg7XG4gICAgY29uc3QgcGFkc1JhbmsgPSBhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoO1xuICAgIGxldCBwYWRDb2RlID0gJyc7XG4gICAgaWYgKGhhc1BhZHMpIHtcbiAgICAgIHBhZENvZGUgPSBgXG4gICAgICAgICAgICAgICAgaWYgKHhJbmRpY2VzW2pdID49IHVuaWZvcm1zLnhfc2hhcGVbal0pIHtcbiAgICAgICAgICAgICAgICAgIHBhZCsrO1xuICAgICAgICAgICAgICAgICAgaXNQYWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmICghaXNQYWQpIHtcbiAgICAgICAgICAgICAgICBsZXQgeF92YWwgPSB4WyR7eC5pbmRpY2VzVG9PZmZzZXQoJ3hJbmRpY2VzJyl9XTtcbiAgICAgICAgICAgICAgICAke29wMX1cbiAgICAgICAgICAgICAgfWA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBhZENvZGUgPSBgXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgbGV0IHhfdmFsID0geFske3guaW5kaWNlc1RvT2Zmc2V0KCd4SW5kaWNlcycpfV07XG4gICAgICAgICAgICAgICR7b3AxfVxuICAgICAgICAgICAgYDtcbiAgICB9XG4gICAgY29uc3QgcG9vbGluZ0NvZGUgPSBgXG4gICAgICAgICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKHgsIG91dHB1dCl9XG5cbiAgICAgICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRTaXplJyl9XG4gICAgICAgICAgICAgIGxldCBpbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuICAgICAgICAgICAgICB2YXIgeEluZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG5cbiAgICAgICAgICAgICAgdmFyIG9mZnNldHM6IGFycmF5PHUzMiwgJHtzdHJpZGVzUmFua30+O1xuXG4gICAgICAgICAgICAgIHZhciB2YWx1ZSA9ICR7ZGF0YVR5cGV9KCR7c3RhcnR9KTtcbiAgICAgICAgICAgICAgdmFyIHBhZCA9IDA7XG4gICAgICAgICAgICAgIHZhciBpc1BhZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgIGZvciAodmFyIGk6IHUzMiA9IDB1OyBpIDwgdW5pZm9ybXMua2VybmVsU2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIG9mZnNldCA9IGk7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDB1OyBqIDwgJHtzdHJpZGVzUmFuayAtIDF9dTsgaisrKSB7XG4gICAgICAgICAgICAgICAgICBvZmZzZXRzW2pdID0gb2Zmc2V0IC8gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLmtlcm5lbFN0cmlkZXMnLCAnaicsIHN0cmlkZXNSYW5rKX07XG4gICAgICAgICAgICAgICAgICBvZmZzZXQgLT0gb2Zmc2V0c1tqXSAqICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5rZXJuZWxTdHJpZGVzJywgJ2onLCBzdHJpZGVzUmFuayl9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvZmZzZXRzWyR7c3RyaWRlc1JhbmsgLSAxfV0gPSBvZmZzZXQ7XG5cbiAgICAgICAgICAgICAgICBpc1BhZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAke3JhbmsgLSBzdHJpZGVzUmFua311OyBqIDwgJHtyYW5rfXU7IGorKykge1xuICAgICAgICAgICAgICAgICAgeEluZGljZXNbal0gPSBpbmRpY2VzW2pdICogJHtnZXRFbGVtZW50QXQoXG4gICAgICAgICAgICAgICAgICAgICd1bmlmb3Jtcy5zdHJpZGVzJyxcbiAgICAgICAgICAgICAgICAgICAgYGogLSAke3JhbmsgLSBzdHJpZGVzUmFua311YCxcbiAgICAgICAgICAgICAgICAgICAgc3RyaWRlc1JhbmssXG4gICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgICAgICArIG9mZnNldHNbaiAtICR7cmFuayAtIHN0cmlkZXNSYW5rfXVdIC0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnBhZHMnLCAnaiAtIDJ1JywgcGFkc1JhbmspfTtcbiAgICAgICAgICAgICAgICAgICR7cGFkQ29kZX1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAke29wMn1cblxuICAgICAgICAgICAgICBvdXRwdXRbZ2xvYmFsX2lkeF0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH1gO1xuICAgIHJldHVybiBwb29saW5nQ29kZTtcbiAgfVxufTtcblxuZXhwb3J0IGludGVyZmFjZSBGb3JtYXRBdHRyaWJ1dGVzIHtcbiAgcmVhZG9ubHkgZm9ybWF0OiAnTkhXQycgfCAnTkNIVyc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUG9vbENvbW1vbkF0dHJpYnV0ZXMgZXh0ZW5kcyBGb3JtYXRBdHRyaWJ1dGVzIHtcbiAgcmVhZG9ubHkgYXV0b1BhZDogc3RyaW5nO1xuICByZWFkb25seSBjZWlsTW9kZTogbnVtYmVyO1xuICByZWFkb25seSBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW107XG4gIHJlYWRvbmx5IHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBwYWRzOiByZWFkb25seSBudW1iZXJbXTtcbn1cblxuY29uc3QgY3JlYXRlU2hhZGVyS2V5RnJvbUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUG9vbENvbW1vbkF0dHJpYnV0ZXMpOiBzdHJpbmcgPT5cbiAgYCR7YXR0cmlidXRlcy5mb3JtYXR9OyR7YXR0cmlidXRlcy5jZWlsTW9kZX07JHthdHRyaWJ1dGVzLmF1dG9QYWR9OyR7YXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGh9YDtcblxuY29uc3QgY3JlYXRlQXZlcmFnZVBvb2xTaGFkZXJLZXlGcm9tQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMpOiBzdHJpbmcgPT5cbiAgYCR7Y3JlYXRlU2hhZGVyS2V5RnJvbUF0dHJpYnV0ZXMoYXR0cmlidXRlcyl9OyR7YXR0cmlidXRlcy5jb3VudEluY2x1ZGVQYWR9YDtcblxuY29uc3QgY3JlYXRlTWF4UG9vbFNoYWRlcktleUZyb21BdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IE1heFBvb2xBdHRyaWJ1dGVzKTogc3RyaW5nID0+XG4gIGAke2NyZWF0ZVNoYWRlcktleUZyb21BdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpfTske2F0dHJpYnV0ZXMuc3RvcmFnZU9yZGVyfTske2F0dHJpYnV0ZXMuZGlsYXRpb25zfWA7XG5cbmNvbnN0IHBhcnNlUG9vbENvbW1vbkF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBQb29sQ29tbW9uQXR0cmlidXRlcyA9PiAoe1xuICBmb3JtYXQ6IGF0dHJpYnV0ZXMuZm9ybWF0IGFzIEZvcm1hdEF0dHJpYnV0ZXNbJ2Zvcm1hdCddLFxuICBhdXRvUGFkOiBbJ05PVFNFVCcsICdWQUxJRCcsICdTQU1FX1VQUEVSJywgJ1NBTUVfTE9XRVInXVthdHRyaWJ1dGVzLmF1dG9fcGFkIGFzIG51bWJlcl0sXG4gIGNlaWxNb2RlOiBhdHRyaWJ1dGVzLmNlaWxfbW9kZSBhcyBudW1iZXIsXG4gIGtlcm5lbFNoYXBlOiBhdHRyaWJ1dGVzLmtlcm5lbF9zaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdLFxuICBzdHJpZGVzOiBhdHRyaWJ1dGVzLnN0cmlkZXMgYXMgW251bWJlciwgbnVtYmVyXSxcbiAgcGFkczogYXR0cmlidXRlcy5wYWRzIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLFxufSk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXZlcmFnZVBvb2xBdHRyaWJ1dGVzIGV4dGVuZHMgUG9vbENvbW1vbkF0dHJpYnV0ZXMsIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGNvdW50SW5jbHVkZVBhZDogYm9vbGVhbjtcbn1cblxuY29uc3QgY3JlYXRlQXZlcmFnZVBvb2xQcm9ncmFtSW5mbyA9IChcbiAgbmFtZTogc3RyaW5nLFxuICBpbnB1dDogVGVuc29yVmlldyxcbiAgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbixcbiAgYXR0cmlidXRlczogQXZlcmFnZVBvb2xBdHRyaWJ1dGVzLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBbYWRqdXN0ZWRBdHRyaWJ1dGVzLCBvdXRwdXRTaGFwZV0gPSBnZXRBZGp1c3RlZFBvb2xBdHRyaWJ1dGVzQW5kT3V0cHV0U2hhcGUoXG4gICAgaW5wdXQsXG4gICAgYXR0cmlidXRlcyxcbiAgICBpc0dsb2JhbE9wZXJhdG9yLFxuICApO1xuICBjb25zdCB4ID0gaW5wdXRWYXJpYWJsZSgneCcsIGlucHV0LmRhdGFUeXBlLCBpbnB1dC5kaW1zLmxlbmd0aCk7XG4gIGNvbnN0IGRhdGFUeXBlID0geC50eXBlLnZhbHVlO1xuXG4gIGNvbnN0IG9wMSA9ICd2YWx1ZSArPSB4X3ZhbDsnO1xuICBsZXQgb3AyID0gJyc7XG4gIGlmIChhZGp1c3RlZEF0dHJpYnV0ZXMuY291bnRJbmNsdWRlUGFkKSB7XG4gICAgb3AyICs9IGB2YWx1ZSAvPSAke2RhdGFUeXBlfSh1bmlmb3Jtcy5rZXJuZWxTaXplKTtgO1xuICB9IGVsc2Uge1xuICAgIG9wMiArPSBgdmFsdWUgLz0gJHtkYXRhVHlwZX0oaTMyKHVuaWZvcm1zLmtlcm5lbFNpemUpIC0gcGFkKTtgO1xuICB9XG4gIGNvbnN0IFtwcm9ncmFtVW5pZm9ybXMsIHVuaWZvcm1zLCBoYXNQYWRzLCBwd1N0YXJ0RW5kTm90WmVybywgcGhTdGFydEVuZE5vdFplcm9dID0gZ2V0VW5pZm9ybUFuZFBhZEluZm8oXG4gICAgb3V0cHV0U2hhcGUsXG4gICAgYWRqdXN0ZWRBdHRyaWJ1dGVzLFxuICApO1xuICBwcm9ncmFtVW5pZm9ybXMucHVzaCguLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhpbnB1dC5kaW1zLCBvdXRwdXRTaGFwZSkpO1xuICBjb25zdCBpbnB1dERlcGVuZGVuY2llczogUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSA9IFsncmFuayddO1xuICByZXR1cm4ge1xuICAgIG5hbWUsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2F0dHJpYnV0ZXMuY2FjaGVLZXl9OyR7aGFzUGFkc307JHtwd1N0YXJ0RW5kTm90WmVyb307JHtwaFN0YXJ0RW5kTm90WmVyb31gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXMsXG4gICAgfSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dC5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZTogKHNoYWRlckhlbHBlcikgPT5cbiAgICAgIGdlbmVyYXRlUG9vbGluZ0NvZGUoXG4gICAgICAgIHNoYWRlckhlbHBlcixcbiAgICAgICAgeCxcbiAgICAgICAgaW5wdXQuZGltcy5sZW5ndGgsXG4gICAgICAgIG91dHB1dFNoYXBlLmxlbmd0aCxcbiAgICAgICAgYWRqdXN0ZWRBdHRyaWJ1dGVzLFxuICAgICAgICBvcDEsXG4gICAgICAgIG9wMixcbiAgICAgICAgMC4wLFxuICAgICAgICB1bmlmb3JtcyxcbiAgICAgICAgaGFzUGFkcyxcbiAgICAgICAgcHdTdGFydEVuZE5vdFplcm8sXG4gICAgICAgIHBoU3RhcnRFbmROb3RaZXJvLFxuICAgICAgKSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUF2ZXJhZ2VQb29sQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGNvdW50SW5jbHVkZVBhZCA9IChhdHRyaWJ1dGVzLmNvdW50X2luY2x1ZGVfcGFkIGFzIG51bWJlcikgPT09IDAgPyBmYWxzZSA6IHRydWU7XG5cbiAgY29uc3QgYXR0ciA9IHBhcnNlUG9vbENvbW1vbkF0dHJpYnV0ZXMoYXR0cmlidXRlcyk7XG4gIC8vIFRPRE86IHN1cHBvcnQgYXR0cmlidXRlICdjZWlsX21vZGUnXG4gIGlmIChhdHRyLmNlaWxNb2RlICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd1c2luZyBjZWlsKCkgaW4gc2hhcGUgY29tcHV0YXRpb24gaXMgbm90IHlldCBzdXBwb3J0ZWQgZm9yIEF2ZXJhZ2VQb29sJyk7XG4gIH1cbiAgY29uc3QgYXZlcmFnZVBvb2xBdHRyaWJ1dGVzID0geyBjb3VudEluY2x1ZGVQYWQsIC4uLmF0dHIsIGNhY2hlS2V5OiAnJyB9O1xuICByZXR1cm4geyAuLi5hdmVyYWdlUG9vbEF0dHJpYnV0ZXMsIGNhY2hlS2V5OiBjcmVhdGVBdmVyYWdlUG9vbFNoYWRlcktleUZyb21BdHRyaWJ1dGVzKGF2ZXJhZ2VQb29sQXR0cmlidXRlcykgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBhdmVyYWdlUG9vbCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQXZlcmFnZVBvb2xBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUF2ZXJhZ2VQb29sUHJvZ3JhbUluZm8oJ0F2ZXJhZ2VQb29sJywgY29udGV4dC5pbnB1dHNbMF0sIGZhbHNlLCBhdHRyaWJ1dGVzKSk7XG59O1xuXG5jb25zdCBnbG9iYWxQb29sQXR0cmlidXRlcyA9IHtcbiAgYXV0b1BhZDogJycsXG4gIGNlaWxNb2RlOiAwLFxuICBjb3VudEluY2x1ZGVQYWQ6IGZhbHNlLFxuICBrZXJuZWxTaGFwZTogW10sXG4gIHN0cmlkZXM6IFtdLFxuICBwYWRzOiBbXSxcbiAgc3RvcmFnZU9yZGVyOiAwLFxuICBkaWxhdGlvbnM6IFtdLFxufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlR2xvYmFsQXZlcmFnZVBvb2xBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogQXZlcmFnZVBvb2xBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgZm9ybWF0ID0gYXR0cmlidXRlcy5mb3JtYXQgYXMgRm9ybWF0QXR0cmlidXRlc1snZm9ybWF0J107XG4gIHJldHVybiB7IGZvcm1hdCwgLi4uZ2xvYmFsUG9vbEF0dHJpYnV0ZXMsIGNhY2hlS2V5OiBmb3JtYXQgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBnbG9iYWxBdmVyYWdlUG9vbCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQXZlcmFnZVBvb2xBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUF2ZXJhZ2VQb29sUHJvZ3JhbUluZm8oJ0dsb2JhbEF2ZXJhZ2VQb29sJywgY29udGV4dC5pbnB1dHNbMF0sIHRydWUsIGF0dHJpYnV0ZXMpKTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWF4UG9vbEF0dHJpYnV0ZXMgZXh0ZW5kcyBQb29sQ29tbW9uQXR0cmlidXRlcywgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgc3RvcmFnZU9yZGVyOiBudW1iZXI7XG4gIHJlYWRvbmx5IGRpbGF0aW9uczogbnVtYmVyW107XG59XG5cbmNvbnN0IGNyZWF0ZU1heFBvb2xQcm9ncmFtSW5mbyA9IChcbiAgbmFtZTogc3RyaW5nLFxuICBpbnB1dDogVGVuc29yVmlldyxcbiAgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbixcbiAgYXR0cmlidXRlczogTWF4UG9vbEF0dHJpYnV0ZXMsXG4pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IFthZGp1c3RlZEF0dHJpYnV0ZXMsIG91dHB1dFNoYXBlXSA9IGdldEFkanVzdGVkUG9vbEF0dHJpYnV0ZXNBbmRPdXRwdXRTaGFwZShcbiAgICBpbnB1dCxcbiAgICBhdHRyaWJ1dGVzLFxuICAgIGlzR2xvYmFsT3BlcmF0b3IsXG4gICk7XG4gIGNvbnN0IG9wMSA9IGBcbiAgICAgIHZhbHVlID0gbWF4KHhfdmFsLCB2YWx1ZSk7XG4gICAgYDtcbiAgY29uc3Qgb3AyID0gJyc7XG4gIGNvbnN0IHggPSBpbnB1dFZhcmlhYmxlKCd4JywgaW5wdXQuZGF0YVR5cGUsIGlucHV0LmRpbXMubGVuZ3RoKTtcbiAgY29uc3QgaW5wdXREZXBlbmRlbmNpZXM6IFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5W10gPSBbJ3JhbmsnXTtcbiAgY29uc3QgW3Byb2dyYW1Vbmlmb3JtcywgdW5pZm9ybXMsIGhhc1BhZHMsIHB3U3RhcnRFbmROb3RaZXJvLCBwaFN0YXJ0RW5kTm90WmVyb10gPSBnZXRVbmlmb3JtQW5kUGFkSW5mbyhcbiAgICBvdXRwdXRTaGFwZSxcbiAgICBhZGp1c3RlZEF0dHJpYnV0ZXMsXG4gICk7XG4gIHByb2dyYW1Vbmlmb3Jtcy5wdXNoKC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0LmRpbXMsIG91dHB1dFNoYXBlKSk7XG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX07JHtoYXNQYWRzfTske3B3U3RhcnRFbmROb3RaZXJvfTske3BoU3RhcnRFbmROb3RaZXJvfWAsXG4gICAgICBpbnB1dERlcGVuZGVuY2llcyxcbiAgICB9LFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0LmRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwoU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gICAgZ2V0U2hhZGVyU291cmNlOiAoc2hhZGVySGVscGVyKSA9PlxuICAgICAgZ2VuZXJhdGVQb29saW5nQ29kZShcbiAgICAgICAgc2hhZGVySGVscGVyLFxuICAgICAgICB4LFxuICAgICAgICBpbnB1dC5kaW1zLmxlbmd0aCxcbiAgICAgICAgb3V0cHV0U2hhcGUubGVuZ3RoLFxuICAgICAgICBhZGp1c3RlZEF0dHJpYnV0ZXMsXG4gICAgICAgIG9wMSxcbiAgICAgICAgb3AyLFxuICAgICAgICBpbnB1dC5kYXRhVHlwZSA9PT0gRGF0YVR5cGUuZmxvYXQxNiA/IC02NTUwNCA6IC0xZTUsXG4gICAgICAgIHVuaWZvcm1zLFxuICAgICAgICBoYXNQYWRzLFxuICAgICAgICBwd1N0YXJ0RW5kTm90WmVybyxcbiAgICAgICAgcGhTdGFydEVuZE5vdFplcm8sXG4gICAgICApLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IG1heFBvb2wgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IE1heFBvb2xBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZU1heFBvb2xQcm9ncmFtSW5mbygnTWF4UG9vbCcsIGNvbnRleHQuaW5wdXRzWzBdLCBmYWxzZSwgYXR0cmlidXRlcykpO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlTWF4UG9vbEF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBNYXhQb29sQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IHN0b3JhZ2VPcmRlciA9IGF0dHJpYnV0ZXMuc3RvcmFnZV9vcmRlciBhcyBudW1iZXI7XG4gIGNvbnN0IGRpbGF0aW9ucyA9IGF0dHJpYnV0ZXMuZGlsYXRpb25zIGFzIFtudW1iZXIsIG51bWJlcl07XG5cbiAgY29uc3QgYXR0ciA9IHBhcnNlUG9vbENvbW1vbkF0dHJpYnV0ZXMoYXR0cmlidXRlcyk7XG4gIC8vIFRPRE86IHN1cHBvcnQgYXR0cmlidXRlICdjZWlsX21vZGUnIGFuZCAnc3RvcmFnZV9vcmRlcidcbiAgaWYgKHN0b3JhZ2VPcmRlciAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignY29sdW1uIG1ham9yIHN0b3JhZ2Ugb3JkZXIgaXMgbm90IHlldCBzdXBwb3J0ZWQgZm9yIE1heFBvb2wnKTtcbiAgfVxuICBpZiAoYXR0ci5jZWlsTW9kZSAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXNpbmcgY2VpbCgpIGluIHNoYXBlIGNvbXB1dGF0aW9uIGlzIG5vdCB5ZXQgc3VwcG9ydGVkIGZvciBNYXhQb29sJyk7XG4gIH1cbiAgY29uc3QgbWF4UG9vbEF0dHJpYnV0ZXMgPSB7IHN0b3JhZ2VPcmRlciwgZGlsYXRpb25zLCAuLi5hdHRyLCBjYWNoZUtleTogJycgfTtcbiAgcmV0dXJuIHsgLi4ubWF4UG9vbEF0dHJpYnV0ZXMsIGNhY2hlS2V5OiBjcmVhdGVNYXhQb29sU2hhZGVyS2V5RnJvbUF0dHJpYnV0ZXMobWF4UG9vbEF0dHJpYnV0ZXMpIH07XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VHbG9iYWxNYXhQb29sQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IE1heFBvb2xBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgZm9ybWF0ID0gYXR0cmlidXRlcy5mb3JtYXQgYXMgRm9ybWF0QXR0cmlidXRlc1snZm9ybWF0J107XG4gIHJldHVybiB7IGZvcm1hdCwgLi4uZ2xvYmFsUG9vbEF0dHJpYnV0ZXMsIGNhY2hlS2V5OiBmb3JtYXQgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBnbG9iYWxNYXhQb29sID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBNYXhQb29sQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVNYXhQb29sUHJvZ3JhbUluZm8oJ0dsb2JhbE1heFBvb2wnLCBjb250ZXh0LmlucHV0c1swXSwgdHJ1ZSwgYXR0cmlidXRlcykpO1xufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSB9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgZ2V0TWF4Q29tcG9uZW50cyxcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBEZXF1YW50aXplTGluZXJBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgYXhpczogbnVtYmVyO1xuICBibG9ja1NpemU6IG51bWJlcjtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IERlcXVhbnRpemVMaW5lckF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKGlucHV0cy5sZW5ndGggPCAyIHx8IGlucHV0cy5sZW5ndGggPiAzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdEZXF1YW50aXplTGluZWFyIHJlcXVpcmVzIDIgb3IgMyBpbnB1dHMuJyk7XG4gIH1cbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMgJiYgaW5wdXRzWzFdLmRpbXMgPT09IGlucHV0c1syXS5kaW1zKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd4LXNjYWxlIGFuZCB4LXplcm8tcG9pbnQgbXVzdCBoYXZlIHRoZSBzYW1lIHNoYXBlLicpO1xuICB9XG4gIGlmIChpbnB1dHMubGVuZ3RoID09PSAzICYmIGlucHV0c1swXS5kYXRhVHlwZSAhPT0gaW5wdXRzWzJdLmRhdGFUeXBlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd4IGFuZCB4LXplcm8tcG9pbnQgbXVzdCBoYXZlIHRoZSBzYW1lIGRhdGEgdHlwZS4nKTtcbiAgfVxuICBpZiAoaW5wdXRzWzBdLmRhdGFUeXBlID09PSBEYXRhVHlwZS5pbnQzMiAmJiBpbnB1dHMubGVuZ3RoID4gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignSW4gdGhlIGNhc2Ugb2YgZGVxdWFudGl6aW5nIGludDMyIHRoZXJlIGlzIG5vIHplcm8gcG9pbnQuJyk7XG4gIH1cbiAgaWYgKGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gMCAmJiBpbnB1dHNbMV0uZGltcy5sZW5ndGggIT09IDEgJiYgaW5wdXRzWzFdLmRpbXMubGVuZ3RoICE9PSBpbnB1dHNbMF0uZGltcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NjYWxlIGlucHV0IG11c3QgYmUgYSBzY2FsYXIsIGEgMUQgdGVuc29yLCBvciBoYXZlIHRoZSBzYW1lIHJhbmsgYXMgdGhlIGlucHV0IHRlbnNvci4nKTtcbiAgfVxuICAvLyB2YWxpZGF0ZSBzY2FsZSBhbmQgemVyby1wb2ludCBpbnB1dCBzaGFwZXNcbiAgaWYgKGlucHV0cy5sZW5ndGggPiAyKSB7XG4gICAgLy8gemVyby1wb2ludCBpbnB1dCB0eXBlIHNob3VsZCBiZSB0aGUgc2FtZSBhcyBpbnB1dCBkYXRhIHR5cGUuXG4gICAgaWYgKGlucHV0c1swXS5kYXRhVHlwZSAhPT0gaW5wdXRzWzJdLmRhdGFUeXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ggYW5kIHgtemVyby1wb2ludCBtdXN0IGhhdmUgdGhlIHNhbWUgZGF0YSB0eXBlLicpO1xuICAgIH1cbiAgICAvLyBTY2FsZSBhbmQgemVyby1wb2ludCBpbnB1dHMgbXVzdCBoYXZlIHRoZSBzYW1lIHNoYXBlXG4gICAgaWYgKGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gaW5wdXRzWzJdLmRpbXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NjYWxlIGFuZCB6ZXJvLXBvaW50IGlucHV0cyBtdXN0IGhhdmUgdGhlIHNhbWUgcmFuay4nKTtcbiAgICB9XG4gICAgaWYgKCFpbnB1dHNbMV0uZGltcy5tYXAoKGQsIGkpID0+IGQgPT09IGlucHV0c1syXS5kaW1zW2ldKS5yZWR1Y2UoKGEsIGIpID0+IGEgJiYgYiwgdHJ1ZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc2NhbGUgYW5kIHplcm8tcG9pbnQgaW5wdXRzIG11c3QgaGF2ZSB0aGUgc2FtZSBzaGFwZS4nKTtcbiAgICB9XG4gIH1cbiAgLy8gVmFsaWRhdGUgYmxvY2tTaXplXG4gIGlmIChhdHRyaWJ1dGVzLmJsb2NrU2l6ZSA+IDApIHtcbiAgICAvLyBCbG9jayBxdW5hdGl6YXRpb25cbiAgICBpZiAoaW5wdXRzWzFdLmRpbXMubGVuZ3RoID09PSAwIHx8IChpbnB1dHNbMV0uZGltcy5sZW5ndGggPT09IDEgJiYgaW5wdXRzWzFdLmRpbXNbMF0gPT09IDEpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Jsb2NrU2l6ZSBtdXN0IGJlIHNldCBvbmx5IGZvciBibG9jayBxdWFudGl6YXRpb24uJyk7XG4gICAgfVxuICAgIGlmIChcbiAgICAgICFpbnB1dHNbMV0uZGltcy5tYXAoKGQsIGkpID0+IGkgPT09IGF0dHJpYnV0ZXMuYXhpcyB8fCBkID09PSBpbnB1dHNbMF0uZGltc1tpXSkucmVkdWNlKChhLCBiKSA9PiBhICYmIGIsIHRydWUpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZvciBibG9jayBxdW5hdGl6YXRpb24sIHNjYWxlIGlucHV0IHNoYXBlIHRvIG1hdGNoIHRoZSBpbnB1dCBzaGFwZSBleGNlcHQgZm9yIHRoZSBheGlzJyk7XG4gICAgfVxuICAgIC8vIFNjYWxlIGlucHV0IHJhbmsgc2hvdWxkIGJlIHNhbWUgYXMgdGhlIGlucHV0IHJhbmtcbiAgICBpZiAoaW5wdXRzWzFdLmRpbXMubGVuZ3RoICE9PSBpbnB1dHNbMF0uZGltcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRm9yIGJsb2NrIHF1bmF0aXphdGlvbiB0aGUgc2NhbGUgaW5wdXQgcmFuayBtdXN0IGJlIHRoZSBzYW1lIGFzIHRoZSB4IHJhbmsuJyk7XG4gICAgfVxuICAgIGNvbnN0IGRJID0gaW5wdXRzWzBdLmRpbXNbYXR0cmlidXRlcy5heGlzXTtcbiAgICBjb25zdCBzaSA9IGlucHV0c1sxXS5kaW1zW2F0dHJpYnV0ZXMuYXhpc107XG4gICAgaWYgKGF0dHJpYnV0ZXMuYmxvY2tTaXplIDwgTWF0aC5jZWlsKGRJIC8gc2kpIHx8IGF0dHJpYnV0ZXMuYmxvY2tTaXplID4gTWF0aC5jZWlsKGRJIC8gKHNpIC0gMSkgLSAxKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdibG9ja1NpemUgbXVzdCBiZSB3aXRoIGluIHRoZSByYW5nZSBbY2VpbChkSSAvIFNpKSwgY2VpbChkSSAvIChTaSAtIDEpIC0gMSldLicpO1xuICAgIH1cbiAgfVxufTtcblxuY29uc3QgY3JlYXRlRGVxdWFudGl6ZUxpbmVhclByb2dyYW1JbmZvID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogRGVxdWFudGl6ZUxpbmVyQXR0cmlidXRlcyxcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgYXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF0dHJpYnV0ZXMuYXhpcywgaW5wdXRzWzBdLmRpbXMubGVuZ3RoKTtcbiAgY29uc3QgaW5wdXRUeXBlID0gaW5wdXRzWzBdLmRhdGFUeXBlO1xuICBjb25zdCBpc1NpZ25lZCA9IGlucHV0VHlwZSA9PT0gRGF0YVR5cGUuaW50ODtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltczsgLy8gb3V0cHV0IHNoYXBlIGlzIHNhbWUgYXMgdGhlIGlucHV0IHNoYXBlXG4gIGNvbnN0IGRhdGFUeXBlID0gaW5wdXRzWzFdLmRhdGFUeXBlOyAvLyBvdXRwdXQgdHlwZSBpcyBzYW1lIGFzIHRoZSB0aGUgc2NhbGUgaW5wdXQgdHlwZVxuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICBjb25zdCBpc1BhY2tlZCA9IGlucHV0VHlwZSA9PT0gRGF0YVR5cGUuaW50OCB8fCBpbnB1dFR5cGUgPT09IERhdGFUeXBlLnVpbnQ4O1xuICBjb25zdCBpbnB1dFNoYXBlID0gaXNQYWNrZWQgPyBbTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplKGlucHV0c1swXS5kaW1zKSAvIDQpXSA6IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBzY2FsZVNoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG4gIGNvbnN0IHplcm9Qb2ludElucHV0ID0gaW5wdXRzLmxlbmd0aCA+IDIgPyBpbnB1dHNbMl0gOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHplcm9Qb2ludFNoYXBlID0gemVyb1BvaW50SW5wdXRcbiAgICA/IGlzUGFja2VkXG4gICAgICA/IFtNYXRoLmNlaWwoU2hhcGVVdGlsLnNpemUoemVyb1BvaW50SW5wdXQuZGltcykgLyA0KV1cbiAgICAgIDogemVyb1BvaW50SW5wdXQuZGltc1xuICAgIDogdW5kZWZpbmVkO1xuICAvLyBTY2FsZXMgaW5wdXQgaXMgYSBzY2FsZXIgZm9yIHBlci10ZW5zb3IvcGVyLWxheWVyIHF1YW50aXphdGlvbiwgMS1EIHRlbnNvciBmb3IgcGVyLWF4aXMgcXVhbnRpemF0aW9uXG4gIC8vIG9yIHRlbnNvciB3aXRoIHNhbWUgcmFuayBhcyBpbnB1dCBmb3IgYmxvY2tlZCBxdWFudGl6YXRpb24uXG4gIGNvbnN0IHBlckxheWVyUXVhbnRpemF0aW9uID0gc2NhbGVTaGFwZS5sZW5ndGggPT09IDAgfHwgKHNjYWxlU2hhcGUubGVuZ3RoID09PSAxICYmIHNjYWxlU2hhcGVbMF0gPT09IDEpO1xuICBjb25zdCBwZXJBeGlzUXVhbnRpemF0aW9uID0gcGVyTGF5ZXJRdWFudGl6YXRpb24gPT09IGZhbHNlICYmIHNjYWxlU2hhcGUubGVuZ3RoID09PSAxO1xuICAvLyBMZWZ0IHVubmVjZXNzYXJ5IGNvbW1lbnRlZC1vdXQgYXNzaWdubWVudCBmb3IgZG9jdW1lbnRhdGlvblxuICAvLyBjb25zdCBibG9ja1F1YW50aXphdGlvbiA9IHBlckxheWVyUXVhbnRpemF0aW9uID09PSBmYWxzZSAmJiBwZXJBeGlzUXVhbnRpemF0aW9uID09PSBmYWxzZTtcbiAgY29uc3QgbWF4Q29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMob3V0cHV0U2l6ZSk7XG4gIGNvbnN0IHVzZUNvbXBvbmVudHMgPSBwZXJMYXllclF1YW50aXphdGlvbiAmJiAoIWlzUGFja2VkIHx8IG1heENvbXBvbmVudHMgPT09IDQpO1xuICBjb25zdCBjb21wb25lbnRzID0gdXNlQ29tcG9uZW50cyA/IG1heENvbXBvbmVudHMgOiAxO1xuICBjb25zdCBpbnB1dENvbXBvbmVudCA9IHVzZUNvbXBvbmVudHMgJiYgIWlzUGFja2VkID8gbWF4Q29tcG9uZW50cyA6IDE7XG4gIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBpc1BhY2tlZCA/IERhdGFUeXBlLnVpbnQzMiA6IGlucHV0VHlwZSwgaW5wdXRTaGFwZS5sZW5ndGgsIGlucHV0Q29tcG9uZW50KTtcbiAgY29uc3Qgc2NhbGUgPSBpbnB1dFZhcmlhYmxlKCdzY2FsZScsIGRhdGFUeXBlLCBzY2FsZVNoYXBlLmxlbmd0aCk7XG4gIGNvbnN0IHplcm9Qb2ludCA9IHplcm9Qb2ludElucHV0XG4gICAgPyBpbnB1dFZhcmlhYmxlKCd6ZXJvX3BvaW50JywgaXNQYWNrZWQgPyBEYXRhVHlwZS51aW50MzIgOiBpbnB1dFR5cGUsIHplcm9Qb2ludFNoYXBlIS5sZW5ndGgpXG4gICAgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBkYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoLCBjb21wb25lbnRzKTtcbiAgY29uc3QgaW5wdXRWYXJpYWJsZXMgPSBbaW5wdXQsIHNjYWxlXTtcbiAgaWYgKHplcm9Qb2ludCkge1xuICAgIGlucHV0VmFyaWFibGVzLnB1c2goemVyb1BvaW50KTtcbiAgfVxuICBjb25zdCBpbnB1dFNoYXBlcyA9IFtpbnB1dFNoYXBlLCBzY2FsZVNoYXBlXTtcbiAgaWYgKHplcm9Qb2ludElucHV0KSB7XG4gICAgaW5wdXRTaGFwZXMucHVzaCh6ZXJvUG9pbnRTaGFwZSEpO1xuICB9XG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSAvIGNvbXBvbmVudHMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogYXhpcyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBhdHRyaWJ1dGVzLmJsb2NrU2l6ZSB9LFxuICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKC4uLmlucHV0U2hhcGVzLCBvdXRwdXRTaGFwZSksXG4gIF07XG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ291dHB1dF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2F4aXMnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnYmxvY2tfc2l6ZScsIHR5cGU6ICd1MzInIH0sXG4gICAgXTtcbiAgICByZXR1cm4gYFxuICAgICAgJHtzaGFkZXJIZWxwZXIucmVnaXN0ZXJVbmlmb3Jtcyh1bmlmb3JtcykuZGVjbGFyZVZhcmlhYmxlcyguLi5pbnB1dFZhcmlhYmxlcywgb3V0cHV0KX1cbiAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgICAgICAgbGV0IG91dHB1dF9pbmRpY2VzID0gJHtvdXRwdXQub2Zmc2V0VG9JbmRpY2VzKCdnbG9iYWxfaWR4Jyl9O1xuXG4gICAgICAgICAgLy8gU2V0IGlucHV0IHhcbiAgICAgICAgICAkeygoKSA9PiB7XG4gICAgICAgICAgICBpZiAoaXNQYWNrZWQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICAgIGxldCBpbnB1dCA9ICR7aW5wdXQuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHggLyA0Jyl9O1xuICAgICAgICAgICAgbGV0IHhfdmVjID0gJHtpc1NpZ25lZCA/ICd1bnBhY2s0eEk4KGlucHV0KScgOiAndW5wYWNrNHhVOChpbnB1dCknfTtcbiAgICAgICAgICAgIGxldCB4X3ZhbHVlID0gJHtjb21wb25lbnRzID09PSAxID8gJ3hfdmVjW2dsb2JhbF9pZHggJSA0XScgOiAneF92ZWMnfTtgO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGBsZXQgeF92YWx1ZSA9ICR7aW5wdXQuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKX07YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSgpfTtcblxuICAgICAgICAgIC8vIFNldCBzY2FsZSBpbnB1dFxuICAgICAgICAgICR7KCgpID0+IHtcbiAgICAgICAgICAgIGlmIChwZXJMYXllclF1YW50aXphdGlvbikge1xuICAgICAgICAgICAgICAvLyBzY2FsZSBpbnB1dCBpcyBhIHNjYWxhciAoKVxuICAgICAgICAgICAgICByZXR1cm4gYGxldCBzY2FsZV92YWx1ZT0gJHtzY2FsZS5nZXRCeU9mZnNldCgnMCcpfWA7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHBlckF4aXNRdWFudGl6YXRpb24pIHtcbiAgICAgICAgICAgICAgLy8gc2NhbGUgaW5wdXQgaXMgYSAxRCB0ZW5zb3JcbiAgICAgICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICAgIGxldCBzY2FsZV9pbmRleCA9ICR7b3V0cHV0LmluZGljZXNHZXQoJ291dHB1dF9pbmRpY2VzJywgJ3VuaWZvcm1zLmF4aXMnKX07XG4gICAgICAgICAgICBsZXQgc2NhbGVfdmFsdWU9ICR7c2NhbGUuZ2V0QnlPZmZzZXQoJ3NjYWxlX2luZGV4Jyl9O2A7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBCbG9jayBxdWFudGl6YXRpb24uIFNjYWxlIGlucHV0IHJhbmsgaXMgc2FtZSBhcyBpbnB1dC9vdXRwdXQgcmFuay5cbiAgICAgICAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICAgIHZhciBzY2FsZV9pbmRpY2VzOiAke3NjYWxlLnR5cGUuaW5kaWNlc30gPSBvdXRwdXRfaW5kaWNlcztcbiAgICAgICAgICAgIGxldCBpbmRleCA9ICR7c2NhbGUuaW5kaWNlc0dldCgnc2NhbGVfaW5kaWNlcycsICd1bmlmb3Jtcy5heGlzJyl9IC8gdW5pZm9ybXMuYmxvY2tfc2l6ZTtcbiAgICAgICAgICAgICR7c2NhbGUuaW5kaWNlc1NldCgnc2NhbGVfaW5kaWNlcycsICd1bmlmb3Jtcy5heGlzJywgJ2luZGV4Jyl9O1xuICAgICAgICAgICAgbGV0IHNjYWxlX3ZhbHVlPSAke3NjYWxlLmdldEJ5SW5kaWNlcygnc2NhbGVfaW5kaWNlcycpfTtgO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pKCl9O1xuXG4gICAgICAgICAgLy8gU2V0IHplcm8tcG9pbnQgaW5wdXRcbiAgICAgICAgICAkeygoKSA9PiB7XG4gICAgICAgICAgICBpZiAoemVyb1BvaW50KSB7XG4gICAgICAgICAgICAgIGlmIChwZXJMYXllclF1YW50aXphdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIHplcm8tcG9pbnQgaW5wdXQgaXMgYSBzY2FsYXJcbiAgICAgICAgICAgICAgICBpZiAoaXNQYWNrZWQpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfaW5wdXQgPSAke3plcm9Qb2ludC5nZXRCeU9mZnNldCgnMCcpfTtcbiAgICAgICAgICAgICAgICBsZXQgemVyb19wb2ludF92ZWMgPSAgJHtpc1NpZ25lZCA/ICd1bnBhY2s0eEk4KHplcm9fcG9pbnRfaW5wdXQpJyA6ICd1bnBhY2s0eFU4KHplcm9fcG9pbnRfaW5wdXQpJ307XG4gICAgICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfdmFsdWU9IHplcm9fcG9pbnRfdmVjWzBdYDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIGBsZXQgemVyb19wb2ludF92YWx1ZSA9ICR7emVyb1BvaW50LmdldEJ5T2Zmc2V0KCcwJyl9YDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAocGVyQXhpc1F1YW50aXphdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIHplcm8tcG9pbnQgaW5wdXQgaXMgYSAxRCB0ZW5zb3JcbiAgICAgICAgICAgICAgICBpZiAoaXNQYWNrZWQpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfaW5kZXggPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRfaW5kaWNlcycsICd1bmlmb3Jtcy5heGlzJyl9O1xuICAgICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X2lucHV0ID0gJHt6ZXJvUG9pbnQuZ2V0QnlPZmZzZXQoJ3plcm9fcG9pbnRfaW5kZXggLyA0Jyl9O1xuICAgICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X3ZlYyA9ICAke2lzU2lnbmVkID8gJ3VucGFjazR4STgoemVyb19wb2ludF9pbnB1dCknIDogJ3VucGFjazR4VTgoemVyb19wb2ludF9pbnB1dCknfTtcbiAgICAgICAgICAgICAgICBsZXQgemVyb19wb2ludF92YWx1ZSA9IHplcm9fcG9pbnRfdmVjW3plcm9fcG9pbnRfaW5kZXggJSA0XWA7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICAgICAgbGV0IHplcm9fcG9pbnRfaW5kZXggPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRfaW5kaWNlcycsICd1bmlmb3Jtcy5heGlzJyl9O1xuICAgICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X3ZhbHVlID0gJHt6ZXJvUG9pbnQuZ2V0QnlPZmZzZXQoJ3plcm9fcG9pbnRfaW5kZXgnKX07YDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gQmxvY2tlZFF1YW50aXphdGlvbi4gVGhlIHplcm8tcG9pbnQgaW5wdXQgc2hhcGUgaXMgc2FtZSBhcyB0aGUgaW5wdXQgc2hhcGUgZXhjZXB0IGFsb25nIGF4aXMuXG4gICAgICAgICAgICAgICAgaWYgKGlzUGFja2VkKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gYFxuICAgICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X29mZnNldCA9ICR7c2NhbGUuaW5kaWNlc1RvT2Zmc2V0KCdzY2FsZV9pbmRpY2VzJyl9O1xuICAgICAgICAgICAgICAgIGxldCB6ZXJvX3BvaW50X2lucHV0ID0gJHt6ZXJvUG9pbnQuZ2V0QnlPZmZzZXQoJ3plcm9fcG9pbnRfb2Zmc2V0IC8gNCcpfTtcbiAgICAgICAgICAgICAgICBsZXQgemVyb19wb2ludF92ZWMgPSAke2lzU2lnbmVkID8gJ3VucGFjazR4STgoemVyb19wb2ludF9pbnB1dCknIDogJ3VucGFjazR4VTgoemVyb19wb2ludF9pbnB1dCknfTtcbiAgICAgICAgICAgICAgICBsZXQgemVyb19wb2ludF92YWx1ZSA9IHplcm9fcG9pbnRfdmVjW3plcm9fcG9pbnRfb2Zmc2V0ICUgNF07YDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIGBsZXQgemVyb19wb2ludF92YWx1ZSA9ICR7emVyb1BvaW50LmdldEJ5SW5kaWNlcygnc2NhbGVfaW5kaWNlcycpfTtgO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGBsZXQgemVyb19wb2ludF92YWx1ZSA9ICR7aXNQYWNrZWQgPyAoaXNTaWduZWQgPyAnaTMyJyA6ICd1MzInKSA6IGlucHV0LnR5cGUudmFsdWV9KDApO2A7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSkoKX07XG4gICAgICAvLyBDb21wdXRlIGFuZCB3cml0ZSBvdXRwdXRcbiAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgYCR7b3V0cHV0LnR5cGUudmFsdWV9KHhfdmFsdWUgLSB6ZXJvX3BvaW50X3ZhbHVlKSAqIHNjYWxlX3ZhbHVlYCl9O1xuICAgICAgfWA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ0RlcXVhbnRpemVMaW5lYXInLFxuICAgIHNoYWRlckNhY2hlOiB7XG4gICAgICBoaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5LFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IHplcm9Qb2ludCA/IFsncmFuaycsICdyYW5rJywgJ3JhbmsnXSA6IFsncmFuaycsICdyYW5rJ10sXG4gICAgfSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyBjb21wb25lbnRzIC8gNjQpLCB5OiAxLCB6OiAxIH0sXG4gICAgICBwcm9ncmFtVW5pZm9ybXMsXG4gICAgfSksXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgZGVxdWFudGl6ZUxpbmVhciA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogRGVxdWFudGl6ZUxpbmVyQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVEZXF1YW50aXplTGluZWFyUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZURlcXVhbnRpemVMaW5lYXJBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogRGVxdWFudGl6ZUxpbmVyQXR0cmlidXRlcyA9PlxuICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoeyBheGlzOiBhdHRyaWJ1dGVzLmF4aXMgYXMgbnVtYmVyLCBibG9ja1NpemU6IGF0dHJpYnV0ZXMuYmxvY2tTaXplIGFzIG51bWJlciB9KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgZW52IH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8sIFByb2dyYW1Vbmlmb3JtIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgVW5pZm9ybURhdGFFbGVtZW50VHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgdmFsaWRhdGVJbnB1dHNDb250ZW50ID0gKHN0YXJ0OiBudW1iZXIsIGxpbWl0OiBudW1iZXIsIGRlbHRhOiBudW1iZXIpOiB2b2lkID0+IHtcbiAgY29uc3Qgc2FtZVN0YXJ0TGltaXQgPSBzdGFydCA9PT0gbGltaXQ7XG4gIGNvbnN0IGluY3JlYXNpbmdSYW5nZU5lZ2F0aXZlU3RlcCA9IHN0YXJ0IDwgbGltaXQgJiYgZGVsdGEgPCAwO1xuICBjb25zdCBkZWNyZWFzaW5nUmFuZ2VQb3NpdGl2ZVN0ZXAgPSBzdGFydCA+IGxpbWl0ICYmIGRlbHRhID4gMDtcblxuICBpZiAoc2FtZVN0YXJ0TGltaXQgfHwgaW5jcmVhc2luZ1JhbmdlTmVnYXRpdmVTdGVwIHx8IGRlY3JlYXNpbmdSYW5nZVBvc2l0aXZlU3RlcCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlJhbmdlIHRoZXNlIGlucHV0cycgY29udGVudHMgYXJlIGludmFsaWQuXCIpO1xuICB9XG59O1xuXG5jb25zdCBjcmVhdGVSYW5nZVByb2dyYW1JbmZvID0gKHN0YXJ0OiBudW1iZXIsIGxpbWl0OiBudW1iZXIsIGRlbHRhOiBudW1iZXIsIGRhdGFUeXBlOiBEYXRhVHlwZSk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgbnVtRWxlbWVudHMgPSBNYXRoLmFicyhNYXRoLmNlaWwoKGxpbWl0IC0gc3RhcnQpIC8gZGVsdGEpKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGU6IG51bWJlcltdID0gW251bUVsZW1lbnRzXTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IG51bUVsZW1lbnRzO1xuICBjb25zdCBwcm9ncmFtVW5pZm9ybXM6IFByb2dyYW1Vbmlmb3JtW10gPSBbXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IG91dHB1dFNpemUgfSxcbiAgICB7IHR5cGU6IGRhdGFUeXBlLCBkYXRhOiBzdGFydCB9LFxuICAgIHsgdHlwZTogZGF0YVR5cGUsIGRhdGE6IGRlbHRhIH0sXG4gICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMob3V0cHV0U2hhcGUpLFxuICBdO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4ge1xuICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBkYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoKTtcbiAgICBjb25zdCB3Z3NsVHlwZSA9IG91dHB1dC50eXBlLnZhbHVlO1xuICAgIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ291dHB1dFNpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnc3RhcnQnLCB0eXBlOiB3Z3NsVHlwZSBhcyBVbmlmb3JtRGF0YUVsZW1lbnRUeXBlIH0sXG4gICAgICB7IG5hbWU6ICdkZWx0YScsIHR5cGU6IHdnc2xUeXBlIGFzIFVuaWZvcm1EYXRhRWxlbWVudFR5cGUgfSxcbiAgICBdO1xuICAgIHJldHVybiBgXG4gICAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybXModW5pZm9ybXMpLmRlY2xhcmVWYXJpYWJsZXMob3V0cHV0KX1cbiAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dFNpemUnKX1cbiAgICAgICAgb3V0cHV0W2dsb2JhbF9pZHhdID0gdW5pZm9ybXMuc3RhcnQgKyAke3dnc2xUeXBlfShnbG9iYWxfaWR4KSAqIHVuaWZvcm1zLmRlbHRhO1xuICAgICAgfWA7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnUmFuZ2UnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke2RhdGFUeXBlfWAgfSxcbiAgICBnZXRTaGFkZXJTb3VyY2UsXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCByYW5nZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBsZXQgc3RhcnQgPSAwO1xuICBsZXQgbGltaXQgPSAwO1xuICBsZXQgZGVsdGEgPSAwO1xuICBpZiAoY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUgPT09IERhdGFUeXBlLmludDMyKSB7XG4gICAgc3RhcnQgPSBjb250ZXh0LmlucHV0c1swXS5nZXRJbnQzMkFycmF5KClbMF07XG4gICAgbGltaXQgPSBjb250ZXh0LmlucHV0c1sxXS5nZXRJbnQzMkFycmF5KClbMF07XG4gICAgZGVsdGEgPSBjb250ZXh0LmlucHV0c1syXS5nZXRJbnQzMkFycmF5KClbMF07XG4gIH0gZWxzZSBpZiAoY29udGV4dC5pbnB1dHNbMF0uZGF0YVR5cGUgPT09IERhdGFUeXBlLmZsb2F0KSB7XG4gICAgc3RhcnQgPSBjb250ZXh0LmlucHV0c1swXS5nZXRGbG9hdDMyQXJyYXkoKVswXTtcbiAgICBsaW1pdCA9IGNvbnRleHQuaW5wdXRzWzFdLmdldEZsb2F0MzJBcnJheSgpWzBdO1xuICAgIGRlbHRhID0gY29udGV4dC5pbnB1dHNbMl0uZ2V0RmxvYXQzMkFycmF5KClbMF07XG4gIH1cbiAgaWYgKGVudi53ZWJncHUudmFsaWRhdGVJbnB1dENvbnRlbnQpIHtcbiAgICB2YWxpZGF0ZUlucHV0c0NvbnRlbnQoc3RhcnQsIGxpbWl0LCBkZWx0YSk7XG4gIH1cblxuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlUmFuZ2VQcm9ncmFtSW5mbyhzdGFydCwgbGltaXQsIGRlbHRhLCBjb250ZXh0LmlucHV0c1swXS5kYXRhVHlwZSksIHsgaW5wdXRzOiBbXSB9KTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgYXRvbWljT3V0cHV0VmFyaWFibGUsXG4gIGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2NhdHRlck5EQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlZHVjdGlvbjogc3RyaW5nO1xufVxuXG50eXBlIFJlZHVjdGlvblR5cGUgPSAnaTMyJyB8ICd1MzInIHwgJ2YzMic7XG5cbmNvbnN0IGF0b21pY1JlZHVjdGlvblNuaXBwZXQgPSAocmVkdWN0aW9uOiBzdHJpbmcsIHB0cjogc3RyaW5nLCB2OiBzdHJpbmcsIHR5cGU6IFJlZHVjdGlvblR5cGUpID0+IHtcbiAgaWYgKHJlZHVjdGlvbiAhPT0gJ25vbmUnICYmIHR5cGUgIT09ICdpMzInICYmIHR5cGUgIT09ICd1MzInICYmIHR5cGUgIT09ICdmMzInKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnB1dCAke3R5cGV9IGlzIG5vdCBzdXBwb3J0ZWQgd2l0aCByZWR1Y3Rpb24gJHtyZWR1Y3Rpb259LmApO1xuICB9XG5cbiAgY29uc3QgZmxvYXRTdGFydCA9IGB7XG4gICAgICAgICAgICAgICAgdmFyIG9sZFZhbHVlID0gMDtcbiAgICAgICAgICAgICAgICBsb29wIHtcbiAgICAgICAgICAgICAgICAgIGxldCBuZXdWYWx1ZUYzMiA9YDtcbiAgY29uc3QgZmxvYXRFbmQgPSBgO1xuICAgICAgICAgICAgICAgICAgbGV0IG5ld1ZhbHVlID0gYml0Y2FzdDxpMzI+KG5ld1ZhbHVlRjMyKTtcbiAgICAgICAgICAgICAgICAgIGxldCByZXMgPSBhdG9taWNDb21wYXJlRXhjaGFuZ2VXZWFrKCYke3B0cn0sIG9sZFZhbHVlLCBuZXdWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICBpZiByZXMuZXhjaGFuZ2VkIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHJlcy5vbGRfdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9YDtcblxuICBzd2l0Y2ggKHJlZHVjdGlvbikge1xuICAgIGNhc2UgJ25vbmUnOlxuICAgICAgcmV0dXJuIGAke3B0cn09JHt2fTtgO1xuICAgIGNhc2UgJ2FkZCc6XG4gICAgICBpZiAodHlwZSA9PT0gJ2kzMicgfHwgdHlwZSA9PT0gJ3UzMicpIHtcbiAgICAgICAgcmV0dXJuIGBhdG9taWNBZGQoJiR7cHRyfSwgYml0Y2FzdDwke3R5cGV9Pigke3Z9KSk7YDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGF0b21pY0FkZCBvbmx5IHN1cHBvcnRzIHVpbnQvaW50IHR5cGUuIEZvciBmbG9hdCwgd2UgdXNlXG4gICAgICAgIC8vIGF0b21pY0NvbXBhcmVFeGNoYW5nZVdlYWsgdG8gc2ltdWxhdGUuXG4gICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICAgICR7ZmxvYXRTdGFydH1iaXRjYXN0PCR7dHlwZX0+KG9sZFZhbHVlKSArICgke3Z9KSR7ZmxvYXRFbmR9YDtcbiAgICAgIH1cbiAgICBjYXNlICdtYXgnOlxuICAgICAgaWYgKHR5cGUgPT09ICdpMzInIHx8IHR5cGUgPT09ICd1MzInKSB7XG4gICAgICAgIHJldHVybiBgYXRvbWljTWF4KCYke3B0cn0sIGJpdGNhc3Q8JHt0eXBlfT4oJHt2fSkpO2A7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBhdG9taWNNYXggb25seSBzdXBwb3J0cyB1aW50L2ludCB0eXBlLiBGb3IgZmxvYXQsIHdlIHVzZVxuICAgICAgICAvLyBhdG9taWNDb21wYXJlRXhjaGFuZ2VXZWFrIHRvIHNpbXVsYXRlLlxuICAgICAgICByZXR1cm4gYFxuICAgICAgICAgICAgICAgICR7ZmxvYXRTdGFydH1tYXgoYml0Y2FzdDxmMzI+KG9sZFZhbHVlKSwgKCR7dn0pKSR7ZmxvYXRFbmR9YDtcbiAgICAgIH1cbiAgICBjYXNlICdtaW4nOlxuICAgICAgaWYgKHR5cGUgPT09ICdpMzInIHx8IHR5cGUgPT09ICd1MzInKSB7XG4gICAgICAgIHJldHVybiBgYXRvbWljTWluKCYke3B0cn0sIGJpdGNhc3Q8JHt0eXBlfT4oJHt2fSkpO2A7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBhdG9taWNNaW4gb25seSBzdXBwb3J0cyB1aW50L2ludCB0eXBlLiBGb3IgZmxvYXQsIHdlIHVzZVxuICAgICAgICAvLyBhdG9taWNDb21wYXJlRXhjaGFuZ2VXZWFrIHRvIHNpbXVsYXRlLlxuICAgICAgICByZXR1cm4gYCR7ZmxvYXRTdGFydH1taW4oYml0Y2FzdDwke3R5cGV9PihvbGRWYWx1ZSksICgke3Z9KSkke2Zsb2F0RW5kfWA7XG4gICAgICB9XG4gICAgY2FzZSAnbXVsJzpcbiAgICAgIC8vIGF0b21pY011bCBpcyBub3Qgc3VwcG9ydGVkLCB3ZSB1c2UgYXRvbWljQ29tcGFyZUV4Y2hhbmdlV2VhayB0byBzaW11bGF0ZS5cbiAgICAgIHJldHVybiBgJHtmbG9hdFN0YXJ0fShiaXRjYXN0PCR7dHlwZX0+KG9sZFZhbHVlKSAqICgke3Z9KSkke2Zsb2F0RW5kfWA7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZWR1Y3Rpb24gJHtyZWR1Y3Rpb259IGlzIG5vdCBzdXBwb3J0ZWQuYCk7XG4gIH1cbn07XG5cbmNvbnN0IGNhbGNEYXRhT2Zmc2V0U25pcHBldCA9IChkYXRhUmFuazogbnVtYmVyLCBwYXJhbGxlbDogYm9vbGVhbikgPT5cbiAgYCR7XG4gICAgZGF0YVJhbmsgPT09IDFcbiAgICAgID8gYFxuICAgIGxldCBlbGVtZW50X2NvdW50X2RpbSA9IHVuaWZvcm1zLm91dHB1dF9zdHJpZGVzO1xuICAgIGxldCBkaW1fdmFsdWUgPSB1bmlmb3Jtcy5vdXRwdXRfc2hhcGU7YFxuICAgICAgOiBgXG4gICAgbGV0IGVsZW1lbnRfY291bnRfZGltID0gdW5pZm9ybXMub3V0cHV0X3N0cmlkZXNbJHtwYXJhbGxlbCA/ICdpIC0gaW5kaWNlc19zdGFydCcgOiAnaSd9XTtcbiAgICBsZXQgZGltX3ZhbHVlID0gdW5pZm9ybXMub3V0cHV0X3NoYXBlWyR7cGFyYWxsZWwgPyAnaSAtIGluZGljZXNfc3RhcnQnIDogJ2knfSArIHVuaWZvcm1zLmxhc3RfaW5kZXhfZGltZW5zaW9uXTtgXG4gIH1cbiAgICBcbiAgICBpZiAoaW5kZXggPj0gMCkge1xuICAgICAgaWYgKGluZGV4ID49IGkzMihkaW1fdmFsdWUpKSB7XG4gICAgICAgIGluZGV4ID0gaTMyKGRpbV92YWx1ZSAtIDEpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoaW5kZXggPCAtaTMyKGRpbV92YWx1ZSkpIHtcbiAgICAgICAgaW5kZXggPSAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5kZXggKz0gaTMyKGRpbV92YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICAgIGRhdGFfb2Zmc2V0ICs9IHUzMigodTMyKGluZGV4KSAqIGVsZW1lbnRfY291bnRfZGltKSk7YDtcblxuY29uc3QgdXBkYXRlRWxlbWVudHNTbmlwcGV0ID0gKGF0dHJpYnV0ZXM6IFNjYXR0ZXJOREF0dHJpYnV0ZXMsIG91dHB1dFR5cGVWYWx1ZTogUmVkdWN0aW9uVHlwZSwgcGFyYWxsZWw6IGJvb2xlYW4pID0+XG4gIGBmb3IgKHZhciBpID0gMHU7IGkgPCB1bmlmb3Jtcy5udW1fdXBkYXRlc19lbGVtZW50czsgaSsrKSB7XG4gICAgICAgIGxldCB2YWx1ZSA9IHVwZGF0ZXNbdW5pZm9ybXMubnVtX3VwZGF0ZXNfZWxlbWVudHMgKiAke3BhcmFsbGVsID8gJ2dsb2JhbF9pZHgnIDogJ2lkeCd9ICsgaV07XG4gICAgICAgICR7YXRvbWljUmVkdWN0aW9uU25pcHBldChhdHRyaWJ1dGVzLnJlZHVjdGlvbiwgJ291dHB1dFtkYXRhX29mZnNldCArIGldJywgJ3ZhbHVlJywgb3V0cHV0VHlwZVZhbHVlKX1cbiAgICAgIH1gO1xuXG5jb25zdCBjcmVhdGVTY2F0dGVyTkRQcm9ncmFtSW5mbyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogU2NhdHRlck5EQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBpbmRpY2VzU2hhcGUgPSBpbnB1dHNbMV0uZGltcztcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dFNoYXBlO1xuICAvLyBUT0RPOiBzdXBwb3J0IGJvb2wgd2l0aCBjb21wb25lbnRzIDQuXG4gIGNvbnN0IGNvbXBvbmVudHMgPSAxO1xuICBjb25zdCBvdXRwdXRTaXplID0gTWF0aC5jZWlsKFNoYXBlVXRpbC5zaXplKGluZGljZXNTaGFwZSkgLyBjb21wb25lbnRzKTtcbiAgY29uc3QgbGFzdEluZGV4RGltZW5zaW9uID0gaW5kaWNlc1NoYXBlW2luZGljZXNTaGFwZS5sZW5ndGggLSAxXTtcbiAgY29uc3QgbnVtVXBkYXRlc0VsZW1lbnRzID0gU2hhcGVVdGlsLnNpemVGcm9tRGltZW5zaW9uKGlucHV0U2hhcGUsIGxhc3RJbmRleERpbWVuc2lvbik7XG4gIGNvbnN0IG51bUluZGljZXNFbGVtZW50cyA9IFNoYXBlVXRpbC5zaXplRnJvbURpbWVuc2lvbihpbmRpY2VzU2hhcGUsIDApIC8gbGFzdEluZGV4RGltZW5zaW9uO1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBsYXN0SW5kZXhEaW1lbnNpb24gfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogbnVtVXBkYXRlc0VsZW1lbnRzIH0sXG4gICAgLi4uY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMoaW5wdXRzWzFdLmRpbXMsIGlucHV0c1syXS5kaW1zLCBvdXRwdXRTaGFwZSksXG4gIF07XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiB7XG4gICAgY29uc3QgaW5kaWNlcyA9IGlucHV0VmFyaWFibGUoJ2luZGljZXMnLCBpbnB1dHNbMV0uZGF0YVR5cGUsIGlucHV0c1sxXS5kaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgdXBkYXRlcyA9IGlucHV0VmFyaWFibGUoJ3VwZGF0ZXMnLCBpbnB1dHNbMl0uZGF0YVR5cGUsIGlucHV0c1syXS5kaW1zLmxlbmd0aCwgY29tcG9uZW50cyk7XG4gICAgY29uc3Qgb3V0cHV0ID1cbiAgICAgIGF0dHJpYnV0ZXMucmVkdWN0aW9uICE9PSAnbm9uZScgJiYgYXR0cmlidXRlcy5yZWR1Y3Rpb24gIT09ICcnXG4gICAgICAgID8gYXRvbWljT3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUubGVuZ3RoKVxuICAgICAgICA6IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCwgY29tcG9uZW50cyk7XG5cbiAgICByZXR1cm4gYFxuICAgICAgJHtzaGFkZXJIZWxwZXJcbiAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0X3NpemUnLCAndTMyJylcbiAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnbGFzdF9pbmRleF9kaW1lbnNpb24nLCAndTMyJylcbiAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgnbnVtX3VwZGF0ZXNfZWxlbWVudHMnLCAndTMyJylcbiAgICAgICAgLmRlY2xhcmVWYXJpYWJsZXMoaW5kaWNlcywgdXBkYXRlcywgb3V0cHV0KX1cbiAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKCd1bmlmb3Jtcy5vdXRwdXRfc2l6ZScpfVxuICB2YXIgaGFzRHVwbGljYXRlcyA9IGZhbHNlO1xuICBpZiAoJHthdHRyaWJ1dGVzLnJlZHVjdGlvbiA9PT0gJ25vbmUnfSkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgJHtudW1JbmRpY2VzRWxlbWVudHN9OyBpID0gaSArIDEpIHtcbiAgICAgIGZvciAodmFyIGogPSBpICsgMTsgaiA8ICR7bnVtSW5kaWNlc0VsZW1lbnRzfTsgaiA9IGogKyAxKSB7XG4gICAgICAgIHZhciBpbmRleF9pID0gaTMyKGluZGljZXNbaV0ueCk7XG4gICAgICAgIHZhciBpbmRleF9qID0gaTMyKGluZGljZXNbal0ueCk7XG4gICAgICAgIGlmIChpbmRleF9pID09IGluZGV4X2opIHtcbiAgICAgICAgICBoYXNEdXBsaWNhdGVzID0gdHJ1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGhhc0R1cGxpY2F0ZXMpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKCR7YXR0cmlidXRlcy5yZWR1Y3Rpb24gPT09ICdub25lJ30gJiYgaGFzRHVwbGljYXRlcykge1xuICAgIGlmIChnbG9iYWxfaWR4ICE9IDB1KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIFByb2Nlc3MgZWFjaCBpbmRleC11cGRhdGUgcGFpciBpbmRpdmlkdWFsbHkgd2hlbiBkdXBsaWNhdGVzIGV4aXN0XG4gICAgZm9yICh2YXIgaWR4ID0gMHU7IGlkeCA8ICR7bnVtSW5kaWNlc0VsZW1lbnRzfXU7IGlkeCsrKSB7XG4gICAgICB2YXIgZGF0YV9vZmZzZXQgPSAwdTtcbiAgICAgIGZvciAodmFyIGkgPSAwdTsgaSA8IHVuaWZvcm1zLmxhc3RfaW5kZXhfZGltZW5zaW9uOyBpKyspIHtcbiAgICAgICAgdmFyIGluZGV4ID0gaTMyKGluZGljZXNbaWR4ICogdW5pZm9ybXMubGFzdF9pbmRleF9kaW1lbnNpb24gKyBpXS54KTtcbiAgICAgICAgJHtjYWxjRGF0YU9mZnNldFNuaXBwZXQoaW5wdXRTaGFwZS5sZW5ndGgsIGZhbHNlKX1cbiAgICAgIH1cbiAgICAgICR7dXBkYXRlRWxlbWVudHNTbmlwcGV0KGF0dHJpYnV0ZXMsIG91dHB1dC50eXBlLnZhbHVlIGFzIFJlZHVjdGlvblR5cGUsIGZhbHNlKX1cbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIGRhdGFfb2Zmc2V0ID0gMHU7XG4gIHZhciBpbmRpY2VzX3N0YXJ0ID0gdW5pZm9ybXMubGFzdF9pbmRleF9kaW1lbnNpb24gKiBnbG9iYWxfaWR4O1xuICB2YXIgaW5kaWNlc19lbmQgPSBpbmRpY2VzX3N0YXJ0ICsgdW5pZm9ybXMubGFzdF9pbmRleF9kaW1lbnNpb247XG4gIGZvciAodmFyIGkgPSBpbmRpY2VzX3N0YXJ0OyBpIDwgaW5kaWNlc19lbmQ7IGkrKykge1xuICAgIHZhciBpbmRleCA9IGkzMihpbmRpY2VzW2ldLngpO1xuICAgICR7Y2FsY0RhdGFPZmZzZXRTbmlwcGV0KGlucHV0U2hhcGUubGVuZ3RoLCB0cnVlKX1cbiAgfVxuICAke3VwZGF0ZUVsZW1lbnRzU25pcHBldChhdHRyaWJ1dGVzLCBvdXRwdXQudHlwZS52YWx1ZSBhcyBSZWR1Y3Rpb25UeXBlLCB0cnVlKX1cbiAgfWA7XG4gIH07XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ1NjYXR0ZXJORCcsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2F0dHJpYnV0ZXMuY2FjaGVLZXl9XyR7YXR0cmlidXRlcy5yZWR1Y3Rpb259YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnLCAncmFuayddLFxuICAgIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZVNjYXR0ZXJOREF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBTY2F0dGVyTkRBdHRyaWJ1dGVzID0+XG4gIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IHJlZHVjdGlvbjogYXR0cmlidXRlcy5yZWR1Y3Rpb24gYXMgc3RyaW5nIH0pO1xuXG5leHBvcnQgY29uc3Qgc2NhdHRlck5EID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBTY2F0dGVyTkRBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVTY2F0dGVyTkRQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcyksIHtcbiAgICBpbnB1dHM6IFtjb250ZXh0LmlucHV0c1sxXSwgY29udGV4dC5pbnB1dHNbMl1dLFxuICAgIG91dHB1dHM6IFtdLFxuICB9KTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyxcbiAgZ2V0RWxlbWVudEF0LFxuICBJbmRpY2VzSGVscGVyLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbnR5cGUgQ29vcmRpbmF0ZVRyYW5zZm9ybU1vZGUgPVxuICB8ICdoYWxmX3BpeGVsJ1xuICB8ICdhc3ltbWV0cmljJ1xuICB8ICdweXRvcmNoX2hhbGZfcGl4ZWwnXG4gIHwgJ3RmX2hhbGZfcGl4ZWxfZm9yX25uJ1xuICB8ICdhbGlnbl9jb3JuZXJzJ1xuICB8ICd0Zl9jcm9wX2FuZF9yZXNpemUnXG4gIHwgJ2hhbGZfcGl4ZWxfc3ltbWV0cmljJztcblxudHlwZSBLZWVwQXNwZWN0UmF0aW9Qb2xpY3kgPSAnc3RyZXRjaCcgfCAnbm90X3NtYWxsZXInIHwgJ25vdF9sYXJnZXInO1xuXG50eXBlIE1vZGUgPSAnbmVhcmVzdCcgfCAnbGluZWFyJyB8ICdjdWJpYyc7XG5cbnR5cGUgTmVhcmVzdE1vZGUgPSAncm91bmRfcHJlZmVyX2Zsb29yJyB8ICdyb3VuZF9wcmVmZXJfY2VpbCcgfCAnZmxvb3InIHwgJ2NlaWwnIHwgJ3NpbXBsZSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzaXplQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIGFudGlhbGlhczogbnVtYmVyO1xuICBheGVzOiBudW1iZXJbXTtcbiAgY29vcmRpbmF0ZVRyYW5zZm9ybU1vZGU6IENvb3JkaW5hdGVUcmFuc2Zvcm1Nb2RlO1xuICBjdWJpY0NvZWZmQTogbnVtYmVyO1xuICBleGNsdWRlT3V0c2lkZTogYm9vbGVhbjtcbiAgZXh0cmFwb2xhdGlvblZhbHVlOiBudW1iZXI7XG4gIGtlZXBBc3BlY3RSYXRpb1BvbGljeTogS2VlcEFzcGVjdFJhdGlvUG9saWN5O1xuICBtb2RlOiBNb2RlO1xuICBuZWFyZXN0TW9kZTogTmVhcmVzdE1vZGU7XG59XG5cbmNvbnN0IHZhbGlkYXRlU2NhbGVzID0gKHNjYWxlczogbnVtYmVyW10sIGF0dHJpYnV0ZXM6IFJlc2l6ZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgc2NhbGVzLmV2ZXJ5KFxuICAgICh2YWx1ZSkgPT5cbiAgICAgIHZhbHVlID4gMCB8fFxuICAgICAgKCgpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZXNpemUgcmVxdWlyZXMgc2NhbGVzIGlucHV0IHZhbHVlcyB0byBiZSBwb3NpdGl2ZScpO1xuICAgICAgfSksXG4gICk7XG4gIC8vIENoZWNrIHNjYWxlcyBkaW1zIGJhc2VkIG9uIG1vZGU6IExJTkVBUiwgQ1VCSUNcbiAgaWYgKHNjYWxlcy5sZW5ndGggPiAwKSB7XG4gICAgaWYgKGF0dHJpYnV0ZXMubW9kZSA9PT0gJ2xpbmVhcicpIHtcbiAgICAgIGlmIChcbiAgICAgICAgIShcbiAgICAgICAgICBzY2FsZXMubGVuZ3RoID09PSAyIHx8XG4gICAgICAgICAgc2NhbGVzLmxlbmd0aCA9PT0gMyB8fFxuICAgICAgICAgIChzY2FsZXMubGVuZ3RoID09PSA0ICYmIHNjYWxlc1swXSA9PT0gMSAmJiBzY2FsZXNbMV0gPT09IDEpIHx8XG4gICAgICAgICAgKHNjYWxlcy5sZW5ndGggPT09IDQgJiYgc2NhbGVzWzBdID09PSAxICYmIHNjYWxlc1szXSA9PT0gMSkgfHxcbiAgICAgICAgICAoc2NhbGVzLmxlbmd0aCA9PT0gNSAmJiBzY2FsZXNbMF0gPT09IDEgJiYgc2NhbGVzWzFdID09PSAxKVxuICAgICAgICApXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBGb3IgbGluZWFyIG1vZGUsIFJlc2l6ZSByZXF1aXJlcyBzY2FsZXMgdG8gYmUgMkQsIDNELCA0RCB3aXRoIGVpdGhlciB0d28gb3V0ZXJtb3N0IG9yIG9uZSBpbm5lcm1vc3QgYW5kXG4gICAgICAgICAgICBvbmUgb3V0ZXJtb3N0IHNjYWxlIHZhbHVlcyBlcXVhbCB0byAxLCBvciA1RCB3aXRoIHR3byBvdXRlcm1vc3Qgc2NhbGUgdmFsdWVzIGVxdWFsIHRvIDFgLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoYXR0cmlidXRlcy5tb2RlID09PSAnY3ViaWMnKSB7XG4gICAgICBpZiAoXG4gICAgICAgICEoXG4gICAgICAgICAgc2NhbGVzLmxlbmd0aCA9PT0gMiB8fFxuICAgICAgICAgIChzY2FsZXMubGVuZ3RoID09PSA0ICYmIHNjYWxlc1swXSA9PT0gMSAmJiBzY2FsZXNbMV0gPT09IDEpIHx8XG4gICAgICAgICAgKHNjYWxlcy5sZW5ndGggPT09IDQgJiYgc2NhbGVzWzBdID09PSAxICYmIHNjYWxlc1szXSA9PT0gMSlcbiAgICAgICAgKVxuICAgICAgKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignUmVzaXplIHJlcXVpcmVzIHNjYWxlcyBpbnB1dCBzaXplIHRvIGJlIDIgb3IgNCBmb3IgY3ViaWMgbW9kZScpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxuY29uc3QgdXBkYXRlU2NhbGVzID0gKHNjYWxlczogcmVhZG9ubHkgbnVtYmVyW10sIGF4ZXM6IHJlYWRvbmx5IG51bWJlcltdLCByYW5rOiBudW1iZXIpOiBudW1iZXJbXSA9PiB7XG4gIGF4ZXMuZXZlcnkoXG4gICAgKHZhbHVlKSA9PlxuICAgICAgKHZhbHVlID49IDAgJiYgdmFsdWUgPCByYW5rKSB8fFxuICAgICAgKCgpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZXNpemUgcmVxdWlyZXMgYXhlcyBpbnB1dCB2YWx1ZXMgdG8gYmUgcG9zaXRpdmUgYW5kIGxlc3MgdGhhbiByYW5rJyk7XG4gICAgICB9KSxcbiAgKTtcbiAgY29uc3QgbmV3U2NhbGVzID0gbmV3IEFycmF5KHJhbmspLmZpbGwoMS4wKTtcbiAgYXhlcy5mb3JFYWNoKCh2YWx1ZSwgaW5kZXgpID0+IChuZXdTY2FsZXNbdmFsdWVdID0gc2NhbGVzW2luZGV4XSkpO1xuICByZXR1cm4gbmV3U2NhbGVzO1xufTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBSZXNpemVBdHRyaWJ1dGVzLFxuICBvcHNldFZlcnNpb246IG51bWJlcixcbiAgc2NhbGVzOiBudW1iZXJbXSxcbiAgc2l6ZXM6IG51bWJlcltdLFxuICByb2k6IG51bWJlcltdLFxuKTogdm9pZCA9PiB7XG4gIGNvbnN0IFtyb2lJbnB1dEluZGV4LCBzY2FsZXNJbnB1dEluZGV4LCBzaXplc0lucHV0SW5kZXhdID1cbiAgICBvcHNldFZlcnNpb24gPiAxMCA/IFsxLCAyLCAzXSA6IFstMSwgaW5wdXRzLmxlbmd0aCA+IDEgPyAxIDogLTEsIC0xXTtcbiAgY29uc3QgcmFuayA9IGlucHV0c1swXS5kaW1zLmxlbmd0aDtcbiAgaWYgKHJvaUlucHV0SW5kZXggPiAwICYmIGlucHV0cy5sZW5ndGggPiByb2lJbnB1dEluZGV4ICYmIGlucHV0c1tyb2lJbnB1dEluZGV4XS5kaW1zLmxlbmd0aCA+IDApIHtcbiAgICBpbnB1dHNbcm9pSW5wdXRJbmRleF0uZ2V0RmxvYXQzMkFycmF5KCkuZm9yRWFjaCgodmFsdWUpID0+IHJvaS5wdXNoKHZhbHVlKSk7XG4gIH0gZWxzZSBpZiAoYXR0cmlidXRlcy5jb29yZGluYXRlVHJhbnNmb3JtTW9kZSA9PT0gJ3RmX2Nyb3BfYW5kX3Jlc2l6ZScpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Jlc2l6ZSByZXF1aXJlcyBSb0kgaW5wdXQgdG8gYmUgc3BlY2lmaWVkIHdoZW4gY29vcmRpbmF0ZVRyYW5zZm9ybU1vZGUgaXMgdGZDcm9wQW5kUmVzaXplJyk7XG4gIH1cblxuICBpZiAoXG4gICAgc2NhbGVzSW5wdXRJbmRleCA+IDAgJiZcbiAgICBpbnB1dHMubGVuZ3RoID4gc2NhbGVzSW5wdXRJbmRleCAmJlxuICAgIGlucHV0c1tzY2FsZXNJbnB1dEluZGV4XS5kaW1zLmxlbmd0aCA9PT0gMSAmJlxuICAgIGlucHV0c1tzY2FsZXNJbnB1dEluZGV4XS5kaW1zWzBdID4gMFxuICApIHtcbiAgICBpbnB1dHNbc2NhbGVzSW5wdXRJbmRleF0uZ2V0RmxvYXQzMkFycmF5KCkuZm9yRWFjaCgodmFsdWUpID0+IHNjYWxlcy5wdXNoKHZhbHVlKSk7XG4gICAgaWYgKFxuICAgICAgc2NhbGVzLmxlbmd0aCAhPT0gMCAmJlxuICAgICAgc2NhbGVzLmxlbmd0aCAhPT0gcmFuayAmJlxuICAgICAgb3BzZXRWZXJzaW9uID49IDE4ICYmXG4gICAgICBzY2FsZXMubGVuZ3RoICE9PSBhdHRyaWJ1dGVzLmF4ZXMubGVuZ3RoXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Jlc2l6ZSByZXF1aXJlcyBzY2FsZXMgaW5wdXQgc2l6ZSB0byBiZSBzYW1lIGFzIGlucHV0IHJhbmsgb3IgYXhlcyBzaXplIGZvciBvcHNldCAxOCBhbmQgdXAnKTtcbiAgICB9XG4gICAgdmFsaWRhdGVTY2FsZXMoc2NhbGVzLCBhdHRyaWJ1dGVzKTtcbiAgICBpZiAoYXR0cmlidXRlcy5heGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHVwZGF0ZVNjYWxlcyhzY2FsZXMsIGF0dHJpYnV0ZXMuYXhlcywgcmFuaykuZm9yRWFjaCgodmFsdWUsIGluZGV4KSA9PiAoc2NhbGVzW2luZGV4XSA9IHZhbHVlKSk7XG4gICAgfVxuICB9XG4gIGlmIChcbiAgICBzaXplc0lucHV0SW5kZXggPiAwICYmXG4gICAgaW5wdXRzLmxlbmd0aCA+IHNpemVzSW5wdXRJbmRleCAmJlxuICAgIGlucHV0c1tzaXplc0lucHV0SW5kZXhdLmRpbXMubGVuZ3RoID09PSAxICYmXG4gICAgaW5wdXRzW3NpemVzSW5wdXRJbmRleF0uZGltc1swXSA+IDBcbiAgKSB7XG4gICAgaW5wdXRzW3NpemVzSW5wdXRJbmRleF0uZ2V0QmlnSW50NjRBcnJheSgpLmZvckVhY2goKHZhbHVlKSA9PiBzaXplcy5wdXNoKE51bWJlcih2YWx1ZSkpKTtcbiAgICBpZiAoc2l6ZXMubGVuZ3RoICE9PSAwICYmIHNpemVzLmxlbmd0aCAhPT0gcmFuayAmJiBvcHNldFZlcnNpb24gPj0gMTggJiYgc2l6ZXMubGVuZ3RoICE9PSBhdHRyaWJ1dGVzLmF4ZXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Jlc2l6ZSByZXF1aXJlcyBzaXplcyBpbnB1dCBzaXplIHRvIGJlIHNhbWUgYXMgaW5wdXQgcmFuayBvciBheGVzIHNpemUgZm9yIG9wc2V0IDE4IGFuZCB1cCcpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChhdHRyaWJ1dGVzLmF4ZXMubGVuZ3RoID4gMCkge1xuICAgIGlmIChzY2FsZXMubGVuZ3RoICE9PSAwICYmIHNjYWxlcy5sZW5ndGggIT09IGF0dHJpYnV0ZXMuYXhlcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVzaXplIHJlcXVpcmVzIFwic2NhbGVzXCIgaW5wdXQgc2l6ZSB0byBiZSBvZiBheGVzIHJhbmsgd2hlbiBheGVzIGF0dHJpYnV0ZXMgaXMgc3BlY2lmaWVkJyk7XG4gICAgfVxuICAgIGlmIChzaXplcy5sZW5ndGggIT09IDAgJiYgc2l6ZXMubGVuZ3RoICE9PSBhdHRyaWJ1dGVzLmF4ZXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Jlc2l6ZSByZXF1aXJlcyBcInNpemVzXCIgaW5wdXQgc2l6ZSB0byBiZSBvZiByYW5rIGF4ZXMgcmFuayB3aGVuIGF4ZXMgYXR0cmlidXRlcyBpcyBzcGVjaWZpZWQnKTtcbiAgICB9XG4gIH1cbiAgaWYgKHR5cGVvZiBzY2FsZXMgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBzaXplcyAhPT0gJ3VuZGVmaW5lZCcgJiYgc2NhbGVzLmxlbmd0aCA+IDAgJiYgc2l6ZXMubGVuZ3RoID4gcmFuaykge1xuICAgIHRocm93IG5ldyBFcnJvcignUmVzaXplIHJlcXVpcmVzIG9ubHkgb2Ygc2NhbGVzIG9yIHNpemVzIHRvIGJlIHNwZWNpZmllZCcpO1xuICB9XG59O1xuXG5jb25zdCBnZXRTYWZlSW50ZWdlckRpdmlzaW9uID0gKGE6IHN0cmluZywgYjogc3RyaW5nLCBjOiBzdHJpbmcsIGRUeXBlOiBzdHJpbmcpOiBzdHJpbmcgPT4gYFxuICAvLyBUaGUgd2hvbGUgcGFydCBhbmQgdGhlIGZyYWN0aW9uYWwgcGFydCBhcmUgY2FsY3VsYXRlZCBzZXBhcmF0ZWx5IGR1ZSB0byBpbmFjY3VyYWN5IG9mIGZsb2F0aW5nXG4gIC8vIHBvaW50IGRpdmlzaW9uLiBBcyBhbiBleGFtcGxlLCBmMzIoMjEpIC8gZjMyKDcpIG1heSBldmFsdWF0ZSB0byAyLjk5Li4uIGluc3RlYWQgb2YgMywgY2F1c2luZyBhblxuICAvLyBvZmZzZXQtYnktb25lIGVycm9yIGxhdGVyIGluIGZsb29yKCkuXG4gIGxldCBiaWcgPSAoJHthfSkgKiAoJHtifSk7XG4gIGxldCB3aG9sZSA9ICR7ZFR5cGV9KGJpZyAvICgke2N9KSk7XG4gIGxldCBmcmFjdCA9ICR7ZFR5cGV9KGJpZyAlICgke2N9KSkgLyAke2RUeXBlfSgke2N9KTtcbiAgcmV0dXJuIHdob2xlICsgZnJhY3Q7XG5gO1xuXG5jb25zdCBnZXRPcmlnaW5hbENvb3JkaW5hdGVGcm9tUmVzaXplZENvb3JkaW5hdGUgPSAoXG4gIGNvb3JkaW5hdGVUcmFuc2Zlck1vZGU6IENvb3JkaW5hdGVUcmFuc2Zvcm1Nb2RlLFxuICBkVHlwZTogc3RyaW5nLFxuKTogc3RyaW5nID0+XG4gIGBmbiBnZXRPcmlnaW5hbENvb3JkaW5hdGVGcm9tUmVzaXplZENvb3JkaW5hdGUoeFJlc2l6ZWQ6IHUzMiwgeFNjYWxlOiBmMzIsIGxlbmd0aFJlc2l6ZWQ6IHUzMixcbiAgICAgbGVuZ3RoT3JpZ2luYWw6IHUzMiwgcm9pU3RhcnQ6IGYzMiwgcm9pRW5kOiBmMzIpIC0+ICR7ZFR5cGV9IHsgYCArXG4gICgoKSA9PiB7XG4gICAgc3dpdGNoIChjb29yZGluYXRlVHJhbnNmZXJNb2RlKSB7XG4gICAgICBjYXNlICdhc3ltbWV0cmljJzpcbiAgICAgICAgcmV0dXJuIGBcbiAgICAgICAgICBpZiAoeFNjYWxlIDwgMS4wIHx8IGZsb29yKHhTY2FsZSkgIT0geFNjYWxlKSB7XG4gICAgICAgICAgICByZXR1cm4gJHtkVHlwZX0oeFJlc2l6ZWQpIC8gJHtkVHlwZX0oeFNjYWxlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJHtnZXRTYWZlSW50ZWdlckRpdmlzaW9uKCd4UmVzaXplZCcsICdsZW5ndGhPcmlnaW5hbCcsICdsZW5ndGhSZXNpemVkJywgZFR5cGUpfVxuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIGNhc2UgJ3B5dG9yY2hfaGFsZl9waXhlbCc6XG4gICAgICAgIHJldHVybiBgaWYgKGxlbmd0aFJlc2l6ZWQgPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoJHtkVHlwZX0oeFJlc2l6ZWQpICsgMC41KSAvICR7ZFR5cGV9KHhTY2FsZSkgLSAwLjU7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gMC4wO1xuICAgICAgICAgICAgICAgICAgfWA7XG4gICAgICBjYXNlICd0Zl9oYWxmX3BpeGVsX2Zvcl9ubic6XG4gICAgICAgIHJldHVybiBgcmV0dXJuICgke2RUeXBlfSh4UmVzaXplZCkgKyAwLjUpIC8gJHtkVHlwZX0oeFNjYWxlKTtgO1xuICAgICAgY2FzZSAnYWxpZ25fY29ybmVycyc6XG4gICAgICAgIHJldHVybiBgaWYgKGxlbmd0aFJlc2l6ZWQgPT0gMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gMC4wO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgJHtnZXRTYWZlSW50ZWdlckRpdmlzaW9uKCd4UmVzaXplZCcsICdsZW5ndGhPcmlnaW5hbCAtIDEnLCAnbGVuZ3RoUmVzaXplZCAtIDEnLCBkVHlwZSl9XG4gICAgICAgICAgICAgICAgICB9YDtcbiAgICAgIGNhc2UgJ3RmX2Nyb3BfYW5kX3Jlc2l6ZSc6XG4gICAgICAgIHJldHVybiBgaWYgKGxlbmd0aFJlc2l6ZWQgPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAke2RUeXBlfShyb2lTdGFydCkgKiAke2RUeXBlfShsZW5ndGhPcmlnaW5hbCAtIDEpICtcbiAgICAgICAgICAgICAgICAgICAgICAgICgke2RUeXBlfSh4UmVzaXplZCkgKiAke2RUeXBlfShyb2lFbmQgLSByb2lTdGFydCkgKiAke2RUeXBlfShsZW5ndGhPcmlnaW5hbCAtIDEpKSAvXG4gICAgICAgICAgICAgICAgICAgICAgICAke2RUeXBlfShsZW5ndGhSZXNpemVkIC0gMSk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gMC41ICogJHtkVHlwZX0ocm9pU3RhcnQgKyByb2lFbmQpICogJHtkVHlwZX0obGVuZ3RoT3JpZ2luYWwgLSAxKTtcbiAgICAgICAgICAgICAgICAgIH1gO1xuICAgICAgY2FzZSAnaGFsZl9waXhlbF9zeW1tZXRyaWMnOlxuICAgICAgICByZXR1cm4gYGNvbnN0IG91dHB1dFdpZHRoID0gJHtkVHlwZX14U2NhbGUgKiAke2RUeXBlfShsZW5ndGhSZXNpemVkKTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGFkanVzdG1lbnQgPSAke2RUeXBlfShsZW5ndGhSZXNpemVkKSAvIG91dHB1dFdpZHRoO1xuICAgICAgICAgICAgICAgICAgY29uc3QgY2VudGVyID0gJHtkVHlwZX0obGVuZ3RoT3JpZ2luYWwpIC8gMjtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IGNlbnRlciAqICgxIC0gYWRqdXN0bWVudCk7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gb2Zmc2V0ICsgKCgke2RUeXBlfSh4UmVzaXplZCkgKyAwLjUpIC8gJHtkVHlwZX0oeFNjYWxlKSkgLSAwLjU7YDtcbiAgICAgIGNhc2UgJ2hhbGZfcGl4ZWwnOlxuICAgICAgICByZXR1cm4gYHJldHVybiAoKCR7ZFR5cGV9KHhSZXNpemVkKSArIDAuNSkgLyAke2RUeXBlfSh4U2NhbGUpKSAtIDAuNTtgO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb29yZGluYXRlIHRyYW5zZm9ybSBtb2RlICR7Y29vcmRpbmF0ZVRyYW5zZmVyTW9kZX0gaXMgbm90IHN1cHBvcnRlZGApO1xuICAgIH1cbiAgfSkoKSArXG4gICd9JztcblxuY29uc3QgZ2V0TmVhcmVzdFBpeGVsRnJvbU9yaWdpbmFsID0gKG5lYXJlc3RNb2RlOiBOZWFyZXN0TW9kZSwgb3BzZXRWZXJzaW9uOiBudW1iZXIsIGRUeXBlOiBzdHJpbmcpOiBzdHJpbmcgPT5cbiAgYGZuIGdldE5lYXJlc3RQaXhlbEZyb21PcmlnaW5hbCh4T3JpZ2luYWw6ICR7ZFR5cGV9LCBpc0Rvd25TYW1wbGU6IGJvb2wpIC0+ICR7ZFR5cGV9IHtgICtcbiAgKCgpID0+IHtcbiAgICBzd2l0Y2ggKG5lYXJlc3RNb2RlKSB7XG4gICAgICBjYXNlICdyb3VuZF9wcmVmZXJfY2VpbCc6XG4gICAgICAgIHJldHVybiAnaWYgKGZyYWN0KHhPcmlnaW5hbCkgPT0gMC41KSB7IFxcXG4gICAgICAgICAgICByZXR1cm4gY2VpbCh4T3JpZ2luYWwpOyBcXFxuICAgICAgICAgIH0gZWxzZSB7IFxcXG4gICAgICAgICAgICByZXR1cm4gcm91bmQoeE9yaWdpbmFsKTsgXFxcbiAgICAgICAgICB9JztcbiAgICAgIGNhc2UgJ2Zsb29yJzpcbiAgICAgICAgcmV0dXJuICdyZXR1cm4gZmxvb3IoeE9yaWdpbmFsKTsnO1xuICAgICAgY2FzZSAnY2VpbCc6XG4gICAgICAgIHJldHVybiAncmV0dXJuIGNlaWwoeE9yaWdpbmFsKTsnO1xuICAgICAgY2FzZSAncm91bmRfcHJlZmVyX2Zsb29yJzpcbiAgICAgICAgcmV0dXJuICdpZiAoZnJhY3QoeE9yaWdpbmFsKSA9PSAwLjUpIHsgXFxcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZsb29yKHhPcmlnaW5hbCk7IFxcXG4gICAgICAgICAgICAgICAgICB9IGVsc2UgeyBcXFxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm91bmQoeE9yaWdpbmFsKTsgXFxcbiAgICAgICAgICAgICAgICAgIH0nO1xuICAgICAgY2FzZSAnc2ltcGxlJzpcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChvcHNldFZlcnNpb24gPCAxMSkge1xuICAgICAgICAgIHJldHVybiAnaWYgKGlzRG93blNhbXBsZSkgXFxcbiAgICAgICAgICAgICAgICAgICAgeyBcXFxuICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjZWlsKHhPcmlnaW5hbCk7IFxcXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7IFxcXG4gICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHhPcmlnaW5hbDsgXFxcbiAgICAgICAgICAgICAgICAgICAgfSc7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBOZWFyZXN0IG1vZGUgJHtuZWFyZXN0TW9kZX0gaXMgbm90IHN1cHBvcnRlZGApO1xuICAgIH1cbiAgfSkoKSArXG4gICd9JztcblxuY29uc3QgdXBkYXRlUm9JID0gKHJvaTogcmVhZG9ubHkgbnVtYmVyW10sIGF4ZXM6IHJlYWRvbmx5IG51bWJlcltdLCByYW5rOiBudW1iZXIpOiBudW1iZXJbXSA9PiB7XG4gIGNvbnN0IHJvaVRtcCA9IG5ldyBBcnJheShyYW5rKS5maWxsKDApLmNvbmNhdChuZXcgQXJyYXkocmFuaykuZmlsbCgxKSk7XG4gIGNvbnN0IHJvaUxvY2FsID0gcm9pLmxlbmd0aCA9PT0gMCA/IHJvaVRtcCA6IHJvaS5zbGljZSgpO1xuICBpZiAoYXhlcy5sZW5ndGggPiAwKSB7XG4gICAgYXhlcy5mb3JFYWNoKCh2LCBpKSA9PiB7XG4gICAgICByb2lUbXBbdl0gPSByb2lMb2NhbFtpXTtcbiAgICAgIHJvaVRtcFtpICsgcmFua10gPSByb2lMb2NhbFtheGVzLmxlbmd0aCArIGldO1xuICAgIH0pO1xuICAgIHJldHVybiByb2lUbXA7XG4gIH1cbiAgcmV0dXJuIHJvaUxvY2FsO1xufTtcblxuY29uc3QgaW5pdE91dHB1dFNoYXBlID0gKFxuICBpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgc2NhbGVzOiByZWFkb25seSBudW1iZXJbXSxcbiAgc2l6ZXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICBheGVzOiByZWFkb25seSBudW1iZXJbXSxcbik6IG51bWJlcltdID0+IHtcbiAgbGV0IG91dHB1dFNoYXBlOiBudW1iZXJbXSA9IFtdO1xuICBpZiAoc2l6ZXMubGVuZ3RoID4gMCkge1xuICAgIGlmIChheGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIGlucHV0U2hhcGUuZm9yRWFjaCgodikgPT4gb3V0cHV0U2hhcGUucHVzaCh2KSk7XG4gICAgICBpZiAoTWF0aC5tYXgoLi4uYXhlcykgPiBpbnB1dFNoYXBlLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2F4ZXMgaXMgb3V0IG9mIGJvdW5kJyk7XG4gICAgICB9XG4gICAgICBheGVzLmZvckVhY2goKHYsIGkpID0+IChvdXRwdXRTaGFwZVt2XSA9IHNpemVzW2ldKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNpemVzLmZvckVhY2goKHYpID0+IG91dHB1dFNoYXBlLnB1c2godikpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAoc2NhbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZXNpemUgcmVxdWlyZXMgZWl0aGVyIHNjYWxlcyBvciBzaXplcy4nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0cHV0U2hhcGUgPSBpbnB1dFNoYXBlLm1hcCgodmFsdWUsIGluZGV4KSA9PiBNYXRoLnJvdW5kKHZhbHVlICogc2NhbGVzW2luZGV4XSkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gb3V0cHV0U2hhcGU7XG59O1xuXG5jb25zdCBhZGp1c3RPdXRwdXRTaGFwZSA9IChpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgc2NhbGVzOiBudW1iZXJbXSwgYXR0cmlidXRlczogUmVzaXplQXR0cmlidXRlcykgPT4ge1xuICBjb25zdCBzY2FsZUluUG9saWN5ID0gKCgpID0+IHtcbiAgICBzd2l0Y2ggKGF0dHJpYnV0ZXMua2VlcEFzcGVjdFJhdGlvUG9saWN5KSB7XG4gICAgICBjYXNlICdub3RfbGFyZ2VyJzpcbiAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZXMuYXhlcy5sZW5ndGggPiAwXG4gICAgICAgICAgPyBNYXRoLm1pbiguLi5hdHRyaWJ1dGVzLmF4ZXMubWFwKChpKSA9PiBzY2FsZXNbaV0pLCBOdW1iZXIuTUFYX1ZBTFVFKVxuICAgICAgICAgIDogTWF0aC5taW4oLi4uc2NhbGVzLCBOdW1iZXIuTUFYX1ZBTFVFKTtcbiAgICAgIGNhc2UgJ25vdF9zbWFsbGVyJzpcbiAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZXMuYXhlcy5sZW5ndGggPiAwXG4gICAgICAgICAgPyBNYXRoLm1heCguLi5hdHRyaWJ1dGVzLmF4ZXMubWFwKChpKSA9PiBzY2FsZXNbaV0pLCBOdW1iZXIuTUlOX1ZBTFVFKVxuICAgICAgICAgIDogTWF0aC5tYXgoLi4uc2NhbGVzLCBOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgS2VlcCBhc3BlY3QgcmF0aW8gcG9saWN5ICR7YXR0cmlidXRlcy5rZWVwQXNwZWN0UmF0aW9Qb2xpY3l9IGlzIG5vdCBzdXBwb3J0ZWRgKTtcbiAgICB9XG4gIH0pKCk7XG4gIHNjYWxlcy5maWxsKDEuMCwgMCwgc2NhbGVzLmxlbmd0aCk7XG4gIGNvbnN0IGFkanVzdGVkT3V0cHV0U2hhcGUgPSBpbnB1dFNoYXBlLnNsaWNlKCk7XG4gIGlmIChhdHRyaWJ1dGVzLmF4ZXMubGVuZ3RoID4gMCkge1xuICAgIGF0dHJpYnV0ZXMuYXhlcy5mb3JFYWNoKCh2KSA9PiAoc2NhbGVzW3ZdID0gc2NhbGVJblBvbGljeSkpO1xuICAgIGF0dHJpYnV0ZXMuYXhlcy5mb3JFYWNoKCh2KSA9PiAoYWRqdXN0ZWRPdXRwdXRTaGFwZVt2XSA9IE1hdGgucm91bmQoaW5wdXRTaGFwZVt2XSAqIHNjYWxlc1t2XSkpKTtcbiAgfSBlbHNlIHtcbiAgICBzY2FsZXMuZmlsbChzY2FsZUluUG9saWN5LCAwLCBzY2FsZXMubGVuZ3RoKTtcbiAgICBhZGp1c3RlZE91dHB1dFNoYXBlLmZvckVhY2goKHYsIGkpID0+IChhZGp1c3RlZE91dHB1dFNoYXBlW2ldID0gTWF0aC5yb3VuZCh2ICogc2NhbGVzW2ldKSkpO1xuICB9XG4gIHJldHVybiBhZGp1c3RlZE91dHB1dFNoYXBlO1xufTtcblxuY29uc3QgY2FsY3VsYXRlT3JpZ2luYWxJbmRpY2VzRnJvbU91dHB1dEluZGljZXMgPSAoXG4gIG91dHB1dDogSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgc2NhbGVzTGVuZ3RoOiBudW1iZXIsXG4gIHJvaUxlbmd0aDogbnVtYmVyLFxuKTogc3RyaW5nID0+IGBcbiAgICBmbiBjYWxjdWxhdGVPcmlnaW5hbEluZGljZXNGcm9tT3V0cHV0SW5kaWNlcyhvdXRwdXRfaW5kaWNlczogJHtvdXRwdXQudHlwZS5pbmRpY2VzfSkgLT4gYXJyYXk8JHtcbiAgICAgIG91dHB1dC50eXBlLnZhbHVlXG4gICAgfSwgJHtvdXRwdXRTaGFwZS5sZW5ndGh9PiB7XG4gICAgICB2YXIgb3JpZ2luYWxfaW5kaWNlczogYXJyYXk8JHtvdXRwdXQudHlwZS52YWx1ZX0sICR7b3V0cHV0U2hhcGUubGVuZ3RofT47XG4gICAgICBmb3IgKHZhciBpOnUzMiA9IDA7IGkgPCAke291dHB1dFNoYXBlLmxlbmd0aH07IGkrKykge1xuICAgICAgICB2YXIgb3V0cHV0X2luZGV4ID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0X2luZGljZXMnLCAnaScpfTtcbiAgICAgICAgdmFyIHNjYWxlID0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnNjYWxlcycsICdpJywgc2NhbGVzTGVuZ3RoKX07XG4gICAgICAgIHZhciByb2lfbG93ID0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnJvaScsICdpJywgcm9pTGVuZ3RoKX07XG4gICAgICAgIHZhciByb2lfaGkgPSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMucm9pJywgYGkgKyAke2lucHV0U2hhcGUubGVuZ3RofWAsIHJvaUxlbmd0aCl9O1xuICAgICAgICBpZiAoc2NhbGUgPT0gMS4wKSB7XG4gICAgICAgICAgb3JpZ2luYWxfaW5kaWNlc1tpXSA9ICR7b3V0cHV0LnR5cGUudmFsdWV9KG91dHB1dF9pbmRleCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIGlucHV0X3NoYXBlX2kgPSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMuaW5wdXRfc2hhcGUnLCAnaScsIGlucHV0U2hhcGUubGVuZ3RoKX07XG4gICAgICAgICAgdmFyIG91dHB1dF9zaGFwZV9pID0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLm91dHB1dF9zaGFwZScsICdpJywgb3V0cHV0U2hhcGUubGVuZ3RoKX07XG4gICAgICAgICAgb3JpZ2luYWxfaW5kaWNlc1tpXSA9IGdldE9yaWdpbmFsQ29vcmRpbmF0ZUZyb21SZXNpemVkQ29vcmRpbmF0ZShvdXRwdXRfaW5kZXgsIHNjYWxlLCBvdXRwdXRfc2hhcGVfaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0X3NoYXBlX2ksIHJvaV9sb3csIHJvaV9oaSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBvcmlnaW5hbF9pbmRpY2VzO1xuICAgIH1gO1xuXG5jb25zdCBjYWxjdWxhdGVJbnB1dEluZGljZXNGcm9tT3V0cHV0SW5kaWNlcyA9IChcbiAgaW5wdXQ6IEluZGljZXNIZWxwZXIsXG4gIG91dHB1dDogSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgc2NhbGVzTGVuZ3RoOiBudW1iZXIsXG4gIHJvaUxlbmd0aDogbnVtYmVyLFxuICB1c2VFeHRyYXBvbGF0aW9uOiBib29sZWFuLFxuKTogc3RyaW5nID0+IGBcbiAgICBmbiBjYWxjdWxhdGVJbnB1dEluZGljZXNGcm9tT3V0cHV0SW5kaWNlcyhvdXRwdXRfaW5kaWNlczogJHtvdXRwdXQudHlwZS5pbmRpY2VzfSkgLT4gJHtpbnB1dC50eXBlLmluZGljZXN9IHtcbiAgICAgIHZhciBpbnB1dF9pbmRpY2VzOiAke2lucHV0LnR5cGUuaW5kaWNlc307XG4gICAgICBmb3IgKHZhciBpOnUzMiA9IDA7IGkgPCAke291dHB1dFNoYXBlLmxlbmd0aH07IGkrKykge1xuICAgICAgICB2YXIgb3V0cHV0X2luZGV4ID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0X2luZGljZXMnLCAnaScpfTtcbiAgICAgICAgdmFyIGlucHV0X2luZGV4OiB1MzI7XG4gICAgICAgIHZhciBzY2FsZSA9ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5zY2FsZXMnLCAnaScsIHNjYWxlc0xlbmd0aCl9O1xuICAgICAgICBpZiAoc2NhbGUgPT0gMS4wKSB7XG4gICAgICAgICAgaW5wdXRfaW5kZXggPSBvdXRwdXRfaW5kZXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHJvaV9sb3cgPSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMucm9pJywgJ2knLCByb2lMZW5ndGgpfTtcbiAgICAgICAgICB2YXIgcm9pX2hpID0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnJvaScsIGBpICsgJHtpbnB1dFNoYXBlLmxlbmd0aH1gLCByb2lMZW5ndGgpfTtcbiAgICAgICAgICB2YXIgaW5wdXRfc2hhcGVfaSA9ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5pbnB1dF9zaGFwZScsICdpJywgaW5wdXRTaGFwZS5sZW5ndGgpfTtcbiAgICAgICAgICB2YXIgb3V0cHV0X3NoYXBlX2kgPSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMub3V0cHV0X3NoYXBlJywgJ2knLCBvdXRwdXRTaGFwZS5sZW5ndGgpfTtcbiAgICAgICAgICB2YXIgb3JpZ2luYWxfaWR4ID0gZ2V0T3JpZ2luYWxDb29yZGluYXRlRnJvbVJlc2l6ZWRDb29yZGluYXRlKG91dHB1dF9pbmRleCwgc2NhbGUsIG91dHB1dF9zaGFwZV9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRfc2hhcGVfaSwgcm9pX2xvdywgcm9pX2hpKTtcbiAgICAgICAgICBpZiAoISR7dXNlRXh0cmFwb2xhdGlvbn0gfHwgKG9yaWdpbmFsX2lkeCA+PSAwICYmIG9yaWdpbmFsX2lkeCA8ICR7b3V0cHV0LnR5cGUudmFsdWV9KGlucHV0X3NoYXBlX2kpKSkge1xuICAgICAgICAgICAgaWYgKG9yaWdpbmFsX2lkeCA8IDApIHtcbiAgICAgICAgICAgICAgaW5wdXRfaW5kZXggPSAwO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChvcmlnaW5hbF9pZHggPiAke291dHB1dC50eXBlLnZhbHVlfShpbnB1dF9zaGFwZV9pIC0gMSkpIHtcbiAgICAgICAgICAgICAgaW5wdXRfaW5kZXggPSBpbnB1dF9zaGFwZV9pIC0gMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlucHV0X2luZGV4ID0gdTMyKGdldE5lYXJlc3RQaXhlbEZyb21PcmlnaW5hbChvcmlnaW5hbF9pZHgsIHNjYWxlIDwgMSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpbnB1dF9pbmRleCA9IHUzMihvcmlnaW5hbF9pZHgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAke2lucHV0LmluZGljZXNTZXQoJ2lucHV0X2luZGljZXMnLCAnaScsICdpbnB1dF9pbmRleCcpfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGlucHV0X2luZGljZXM7XG4gICAgfWA7XG5jb25zdCBjaGVja0lucHV0SW5kaWNlcyA9IChpbnB1dDogSW5kaWNlc0hlbHBlciwgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pOiBzdHJpbmcgPT4gYFxuICAgIGZuIGNoZWNrSW5wdXRJbmRpY2VzKGlucHV0X2luZGljZXM6ICR7aW5wdXQudHlwZS5pbmRpY2VzfSkgLT4gYm9vbCB7XG4gICAgICBmb3IgKHZhciBpOnUzMiA9IDA7IGkgPCAke2lucHV0U2hhcGUubGVuZ3RofTsgaSsrKSB7XG4gICAgICAgIHZhciBpbnB1dF9pbmRleCA9ICR7aW5wdXQuaW5kaWNlc0dldCgnaW5wdXRfaW5kaWNlcycsICdpJyl9O1xuICAgICAgICBpZiAoaW5wdXRfaW5kZXggPCAwIHx8IGlucHV0X2luZGV4ID49ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5pbnB1dF9zaGFwZScsICdpJywgaW5wdXRTaGFwZS5sZW5ndGgpfSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfWA7XG5cbmNvbnN0IHNldENoYW5uZWxBbmRCYXRjaEluZGljZXMgPSAoXG4gIGlucHV0OiBJbmRpY2VzSGVscGVyLFxuICBjaGFubmVsSWR4OiBudW1iZXIsXG4gIGJhdGNoSWR4OiBudW1iZXIsXG4gIHNwYWNpYWxEaW1zOiBudW1iZXIsXG4pOiBzdHJpbmcgPT5cbiAgaW5wdXQucmFuayA+IHNwYWNpYWxEaW1zXG4gICAgPyBgXG4gICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dF9pbmRpY2VzJywgY2hhbm5lbElkeCwgJ2NoYW5uZWwnKX07XG4gICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dF9pbmRpY2VzJywgYmF0Y2hJZHgsICdiYXRjaCcpfTtcbmBcbiAgICA6ICcnO1xuXG5jb25zdCBiaWxpbmVhckludGVycG9sYXRpb24gPSAoXG4gIGlucHV0OiBJbmRpY2VzSGVscGVyLFxuICBvdXRwdXQ6IEluZGljZXNIZWxwZXIsXG4gIGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICB1c2VFeHRyYXBvbGF0aW9uOiBib29sZWFuLFxuICBleHRyYXBvbGF0aW9uVmFsdWU6IG51bWJlcixcbik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGlzTmNodyA9IHRydWU7XG4gIGNvbnN0IFtiYXRjaElkeCwgaGVpZ2h0SWR4LCB3aWR0aElkeCwgY2hhbm5lbElkeF0gPVxuICAgIGlucHV0U2hhcGUubGVuZ3RoID09PSAyID8gWy0xLCAwLCAxLCAtMV0gOiBpc05jaHcgPyBbMCwgMiwgMywgMV0gOiBbMCwgMSwgMiwgM107XG4gIGNvbnN0IGRUeXBlID0gaW5wdXQudHlwZS52YWx1ZTtcbiAgcmV0dXJuIGBcbiAgICBmbiBnZXRJbnB1dFZhbHVlKGJhdGNoOiB1MzIsIGNoYW5uZWw6IHUzMiwgcm93OiB1MzIsIGNvbDogdTMyKSAtPiAke2RUeXBlfSB7XG4gICAgICB2YXIgaW5wdXRfaW5kaWNlczogJHtpbnB1dC50eXBlLmluZGljZXN9O1xuICAgICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dF9pbmRpY2VzJywgaGVpZ2h0SWR4LCBgbWF4KDAsIG1pbihyb3csICR7aW5wdXRTaGFwZVtoZWlnaHRJZHhdfSAtIDEpKWApfTtcbiAgICAgICR7aW5wdXQuaW5kaWNlc1NldCgnaW5wdXRfaW5kaWNlcycsIHdpZHRoSWR4LCBgbWF4KDAsIG1pbihjb2wsICR7aW5wdXRTaGFwZVt3aWR0aElkeF19IC0gMSkpYCl9O1xuICAgICAgJHtzZXRDaGFubmVsQW5kQmF0Y2hJbmRpY2VzKGlucHV0LCBjaGFubmVsSWR4LCBiYXRjaElkeCwgMil9XG4gICAgICByZXR1cm4gJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX07XG4gICAgfVxuXG4gICAgZm4gYmlsaW5lYXJJbnRlcnBvbGF0aW9uKG91dHB1dF9pbmRpY2VzOiAke291dHB1dC50eXBlLmluZGljZXN9KSAtPiAke2RUeXBlfSB7XG4gICAgICB2YXIgb3JpZ2luYWxJbmRpY2VzID0gY2FsY3VsYXRlT3JpZ2luYWxJbmRpY2VzRnJvbU91dHB1dEluZGljZXMob3V0cHV0X2luZGljZXMpO1xuICAgICAgdmFyIHJvdzoke2RUeXBlfSA9IG9yaWdpbmFsSW5kaWNlc1ske2hlaWdodElkeH1dO1xuICAgICAgdmFyIGNvbDoke2RUeXBlfSA9IG9yaWdpbmFsSW5kaWNlc1ske3dpZHRoSWR4fV07XG4gICAgICAke1xuICAgICAgICB1c2VFeHRyYXBvbGF0aW9uXG4gICAgICAgICAgPyBgaWYgKHJvdyA8IDAgfHwgcm93ID4gKCR7aW5wdXRTaGFwZVtoZWlnaHRJZHhdfSAtIDEpIHx8IGNvbCA8IDAgfHwgY29sID4gKCR7aW5wdXRTaGFwZVt3aWR0aElkeF19IC0gMSkpIHtcbiAgICAgICAgcmV0dXJuICR7ZXh0cmFwb2xhdGlvblZhbHVlfTtcbiAgICAgIH1gXG4gICAgICAgICAgOiAnJ1xuICAgICAgfTtcbiAgICAgIHJvdyA9IG1heCgwLCBtaW4ocm93LCAke2lucHV0U2hhcGVbaGVpZ2h0SWR4XX0gLSAxKSk7XG4gICAgICBjb2wgPSBtYXgoMCwgbWluKGNvbCwgJHtpbnB1dFNoYXBlW3dpZHRoSWR4XX0gLSAxKSk7XG4gICAgICB2YXIgcm93MTogdTMyID0gdTMyKHJvdyk7XG4gICAgICB2YXIgY29sMTogdTMyID0gdTMyKGNvbCk7XG4gICAgICB2YXIgcm93MjogdTMyID0gdTMyKHJvdyArIDEpO1xuICAgICAgdmFyIGNvbDI6IHUzMiA9IHUzMihjb2wgKyAxKTtcbiAgICAgIHZhciBjaGFubmVsOiB1MzIgPSAke2lucHV0U2hhcGUubGVuZ3RoID4gMiA/IGB1MzIob3JpZ2luYWxJbmRpY2VzWyR7Y2hhbm5lbElkeH1dKWAgOiAnMCd9O1xuICAgICAgdmFyIGJhdGNoOiB1MzIgPSAgJHtpbnB1dFNoYXBlLmxlbmd0aCA+IDIgPyBgdTMyKG9yaWdpbmFsSW5kaWNlc1ske2JhdGNoSWR4fV0pYCA6ICcwJ307XG4gICAgICB2YXIgeDExOiAke2RUeXBlfSA9IGdldElucHV0VmFsdWUoYmF0Y2gsIGNoYW5uZWwsIHJvdzEsIGNvbDEpO1xuICAgICAgdmFyIHgxMjogJHtkVHlwZX0gPSBnZXRJbnB1dFZhbHVlKGJhdGNoLCBjaGFubmVsLCByb3cxLCBjb2wyKTtcbiAgICAgIHZhciB4MjE6ICR7ZFR5cGV9ID0gZ2V0SW5wdXRWYWx1ZShiYXRjaCwgY2hhbm5lbCwgcm93MiwgY29sMSk7XG4gICAgICB2YXIgeDIyOiAke2RUeXBlfSA9IGdldElucHV0VmFsdWUoYmF0Y2gsIGNoYW5uZWwsIHJvdzIsIGNvbDIpO1xuICAgICAgdmFyIGR4MTogJHtkVHlwZX0gPSBhYnMocm93IC0gJHtkVHlwZX0ocm93MSkpO1xuICAgICAgdmFyIGR4MjogJHtkVHlwZX0gPSBhYnMoJHtkVHlwZX0ocm93MikgLSByb3cpO1xuICAgICAgdmFyIGR5MTogJHtkVHlwZX0gPSBhYnMoY29sIC0gJHtkVHlwZX0oY29sMSkpO1xuICAgICAgdmFyIGR5MjogJHtkVHlwZX0gPSBhYnMoJHtkVHlwZX0oY29sMikgLSBjb2wpO1xuICAgICAgaWYgKHJvdzEgPT0gcm93Mikge1xuICAgICAgICBkeDEgPSAwLjU7XG4gICAgICAgIGR4MiA9IDAuNTtcbiAgICAgIH1cbiAgICAgIGlmIChjb2wxID09IGNvbDIpIHtcbiAgICAgICAgZHkxID0gMC41O1xuICAgICAgICBkeTIgPSAwLjU7XG4gICAgICB9XG4gICAgICByZXR1cm4gKHgxMSAqIGR4MiAqIGR5MiArIHgxMiAqIGR4MiAqIGR5MSArIHgyMSAqIGR4MSAqIGR5MiArIHgyMiAqIGR4MSAqIGR5MSk7XG4gICAgfWA7XG59O1xuXG5jb25zdCBiaWN1YmljSW50ZXJwb2xhdGlvbiA9IChcbiAgaW5wdXQ6IEluZGljZXNIZWxwZXIsXG4gIG91dHB1dDogSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgc2NhbGVzOiByZWFkb25seSBudW1iZXJbXSxcbiAgcm9pOiByZWFkb25seSBudW1iZXJbXSxcbiAgY3ViaWNDb2VmZkE6IG51bWJlcixcbiAgdXNlRXh0cmFwb2xhdGlvbjogYm9vbGVhbixcbiAgZXh0cmFwb2xhdGlvblZhbHVlOiBudW1iZXIsXG4gIGV4Y2x1ZGVPdXRzaWRlOiBib29sZWFuLFxuKTogc3RyaW5nID0+IHtcbiAgY29uc3QgaXMyRCA9IGlucHV0U2hhcGUubGVuZ3RoID09PSAyO1xuICBjb25zdCBpc05jaHcgPSB0cnVlO1xuICBjb25zdCBbaGVpZ2h0SWR4LCB3aWR0aElkeF0gPSBpczJEID8gWzAsIDFdIDogaXNOY2h3ID8gWzIsIDNdIDogWzEsIDJdO1xuICBjb25zdCBkVHlwZSA9IGlucHV0LnR5cGUudmFsdWU7XG4gIGNvbnN0IGNyZWF0ZUN1YmljSW50ZXJwb2xhdGlvbkZ1bmN0aW9uID0gKGlkeDogbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgICBjb25zdCBkaXJlY3Rpb24gPSBpZHggPT09IGhlaWdodElkeCA/ICdyb3cnIDogJ2NvbCc7XG4gICAgcmV0dXJuIGBcbiAgICAgIGZuICR7ZGlyZWN0aW9ufUN1YmljSW50ZXJwb2xhdGlvbihpbnB1dF9pbmRpY2VzOiAke2lucHV0LnR5cGUuaW5kaWNlc30sIG91dHB1dF9pbmRpY2VzOiAke1xuICAgICAgICBvdXRwdXQudHlwZS5pbmRpY2VzXG4gICAgICB9KSAtPiAke2RUeXBlfSB7XG4gICAgICAgIHZhciBvdXRwdXRfaW5kZXggPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRfaW5kaWNlcycsIGlkeCl9O1xuICAgICAgICB2YXIgb3JpZ2luYWxJZHg6ICR7ZFR5cGV9ID0gZ2V0T3JpZ2luYWxDb29yZGluYXRlRnJvbVJlc2l6ZWRDb29yZGluYXRlKG91dHB1dF9pbmRleCwgJHtzY2FsZXNbaWR4XX0sXG4gICAgICAgICR7b3V0cHV0U2hhcGVbaWR4XX0sICR7aW5wdXRTaGFwZVtpZHhdfSwgJHtyb2lbaWR4XX0sICR7cm9pW2lkeF19ICsgJHtpbnB1dFNoYXBlLmxlbmd0aH0pO1xuICAgICAgICB2YXIgZnJhY3RPcmlnaW5hbElkeDogJHtkVHlwZX0gPSBvcmlnaW5hbElkeCAtIGZsb29yKG9yaWdpbmFsSWR4KTtcbiAgICAgICAgdmFyIGNvZWZzID0gZ2V0Q3ViaWNJbnRlcnBvbGF0aW9uQ29lZnMoZnJhY3RPcmlnaW5hbElkeCk7XG5cbiAgICAgICAgaWYgKCR7dXNlRXh0cmFwb2xhdGlvbn0gJiYgKG9yaWdpbmFsSWR4IDwgMCB8fCBvcmlnaW5hbElkeCA+ICgke2lucHV0U2hhcGVbaWR4XX0gLSAxKSkpIHtcbiAgICAgICAgICByZXR1cm4gJHtleHRyYXBvbGF0aW9uVmFsdWV9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBkYXRhOiBhcnJheTwke2RUeXBlfSwgND4gPSBhcnJheTwke2RUeXBlfSwgND4oMC4wLCAwLjAsIDAuMCwgMC4wKTtcbiAgICAgICAgZm9yICh2YXIgaTogaTMyID0gLTE7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgICB2YXIgJHtkaXJlY3Rpb259OiAke2RUeXBlfSA9IG9yaWdpbmFsSWR4ICsgJHtkVHlwZX0oaSk7XG4gICAgICAgICAgaWYgKCR7ZGlyZWN0aW9ufSA8IDAgfHwgJHtkaXJlY3Rpb259ID49ICR7aW5wdXRTaGFwZVtpZHhdfSkge1xuICAgICAgICAgICAgJHsoKCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoZXhjbHVkZU91dHNpZGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYGNvZWZzW2kgKyAxXSA9IDAuMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO2A7XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAodXNlRXh0cmFwb2xhdGlvbikge1xuICAgICAgICAgICAgICAgIHJldHVybiBgcmV0dXJuICR7ZXh0cmFwb2xhdGlvblZhbHVlfTtgO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBgJHtkaXJlY3Rpb259ID0gbWF4KDAsIG1pbigke2RpcmVjdGlvbn0sICR7aW5wdXRTaGFwZVtpZHhdfSAtIDEpKTtgO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KSgpfTtcbiAgICAgICAgICB9XG4gICAgICAgIHZhciBpbnB1dF9pbmRpY2VzX2NvcHk6ICR7aW5wdXQudHlwZS5pbmRpY2VzfSA9IGlucHV0X2luZGljZXM7XG4gICAgICAgICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dF9pbmRpY2VzX2NvcHknLCBpZHgsIGB1MzIoJHtkaXJlY3Rpb259KWApfTtcbiAgICAgICAgICBkYXRhW2kgKyAxXSA9ICR7XG4gICAgICAgICAgICBpZHggPT09IGhlaWdodElkeFxuICAgICAgICAgICAgICA/IGlucHV0LmdldEJ5SW5kaWNlcygnaW5wdXRfaW5kaWNlc19jb3B5JylcbiAgICAgICAgICAgICAgOiAncm93Q3ViaWNJbnRlcnBvbGF0aW9uKGlucHV0X2luZGljZXNfY29weSwgb3V0cHV0X2luZGljZXMpJ1xuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGN1YmljSW50ZXJwb2xhdGlvbjFEKGRhdGEsIGNvZWZzKTtcbiAgICAgIH1gO1xuICB9O1xuXG4gIHJldHVybiBgXG4gICAgJHtjcmVhdGVDdWJpY0ludGVycG9sYXRpb25GdW5jdGlvbihoZWlnaHRJZHgpfTtcbiAgICAke2NyZWF0ZUN1YmljSW50ZXJwb2xhdGlvbkZ1bmN0aW9uKHdpZHRoSWR4KX07XG4gIGZuIGdldEN1YmljSW50ZXJwb2xhdGlvbkNvZWZzKHM6ICR7ZFR5cGV9KSAtPiBhcnJheTwke2RUeXBlfSwgND4ge1xuICAgIHZhciBhYnNTID0gYWJzKHMpO1xuICAgIHZhciBjb2VmZnM6IGFycmF5PCR7ZFR5cGV9LCA0PiA9IGFycmF5PCR7ZFR5cGV9LCA0PigwLjAsIDAuMCwgMC4wLCAwLjApO1xuICAgIHZhciBvbmVNaW51c0Fic1M6ICR7ZFR5cGV9ID0gMS4wIC0gYWJzUztcbiAgICB2YXIgdHdvTWludXNBYnNTOiAke2RUeXBlfSA9IDIuMCAtIGFic1M7XG4gICAgdmFyIG9uZVBsdXNBYnNTOiAke2RUeXBlfSA9IDEuMCArIGFic1M7XG4gICAgY29lZmZzWzBdID0gKCgke2N1YmljQ29lZmZBfSAqIG9uZVBsdXNBYnNTIC0gNSAqICR7Y3ViaWNDb2VmZkF9KSAqIG9uZVBsdXNBYnNTICsgOCAqICR7XG4gICAgICBjdWJpY0NvZWZmQVxuICAgIH0pICogb25lUGx1c0Fic1MgLSA0ICogJHtjdWJpY0NvZWZmQX07XG4gICAgY29lZmZzWzFdID0gKCgke2N1YmljQ29lZmZBfSArIDIpICogYWJzUyAtICgke2N1YmljQ29lZmZBfSArIDMpKSAqIGFic1MgKiBhYnNTICsgMTtcbiAgICBjb2VmZnNbMl0gPSAoKCR7Y3ViaWNDb2VmZkF9ICsgMikgKiBvbmVNaW51c0Fic1MgLSAoJHtjdWJpY0NvZWZmQX0gKyAzKSkgKiBvbmVNaW51c0Fic1MgKiBvbmVNaW51c0Fic1MgKyAxO1xuICAgIGNvZWZmc1szXSA9ICgoJHtjdWJpY0NvZWZmQX0gKiB0d29NaW51c0Fic1MgLSA1ICogJHtjdWJpY0NvZWZmQX0pICogdHdvTWludXNBYnNTICsgOCAqICR7XG4gICAgICBjdWJpY0NvZWZmQVxuICAgIH0pICogdHdvTWludXNBYnNTIC0gNCAqICR7Y3ViaWNDb2VmZkF9O1xuICAgIHJldHVybiBjb2VmZnM7XG4gIH1cblxuICBmbiBjdWJpY0ludGVycG9sYXRpb24xRCh4OiBhcnJheTwke2RUeXBlfSwgND4sIGNvZWZzOiBhcnJheTwke2RUeXBlfSwgND4pIC0+ICR7ZFR5cGV9IHtcbiAgICB2YXIgY29lZnNTdW06ICR7ZFR5cGV9ID0gY29lZnNbMF0gKyBjb2Vmc1sxXSArIGNvZWZzWzJdICsgY29lZnNbM107XG4gICAgcmV0dXJuICh4WzBdICogY29lZnNbMF0gKyB4WzFdICogY29lZnNbMV0rIHhbMl0gKiBjb2Vmc1syXSsgeFszXSAqIGNvZWZzWzNdKSAvIGNvZWZzU3VtO1xuICB9XG5cbiAgZm4gYmljdWJpY0ludGVycG9sYXRpb24ob3V0cHV0X2luZGljZXM6ICR7b3V0cHV0LnR5cGUuaW5kaWNlc30pIC0+ICR7ZFR5cGV9IHtcbiAgICB2YXIgaW5wdXRfaW5kaWNlczogJHtpbnB1dC50eXBlLmluZGljZXN9ID0gb3V0cHV0X2luZGljZXM7XG4gICAgcmV0dXJuIGNvbEN1YmljSW50ZXJwb2xhdGlvbihpbnB1dF9pbmRpY2VzLCBvdXRwdXRfaW5kaWNlcyk7XG4gIH1cbiAgICBgO1xufTtcblxuY29uc3QgdHJpbGluZWFySW50ZXJwb2xhdGlvbiA9IChcbiAgaW5wdXQ6IEluZGljZXNIZWxwZXIsXG4gIG91dHB1dDogSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHVzZUV4dHJhcG9sYXRpb246IGJvb2xlYW4sXG4gIGV4dHJhcG9sYXRpb25WYWx1ZTogbnVtYmVyLFxuKTogc3RyaW5nID0+IHtcbiAgY29uc3QgaXNOY2h3ID0gdHJ1ZTtcbiAgY29uc3QgW2JhdGNoSWR4LCBkZXB0aElkeCwgaGVpZ2h0SWR4LCB3aWR0aElkeCwgY2hhbm5lbElkeF0gPVxuICAgIGlucHV0U2hhcGUubGVuZ3RoID09PSAzID8gWy0xLCAwLCAxLCAyLCAtMV0gOiBpc05jaHcgPyBbMCwgMiwgMywgNCwgMV0gOiBbMCwgMSwgMiwgMywgNF07XG4gIGNvbnN0IGRUeXBlID0gaW5wdXQudHlwZS52YWx1ZTtcbiAgcmV0dXJuIGBcbiAgICBmbiBnZXRJbnB1dFZhbHVlKGJhdGNoOiB1MzIsIGNoYW5uZWw6IHUzMiwgZGVwdGg6dTMyLCBoZWlnaHQ6IHUzMiwgd2lkdGg6IHUzMikgLT4gJHtkVHlwZX0ge1xuICAgICAgdmFyIGlucHV0X2luZGljZXM6ICR7aW5wdXQudHlwZS5pbmRpY2VzfTtcbiAgICAgICR7aW5wdXQuaW5kaWNlc1NldCgnaW5wdXRfaW5kaWNlcycsIGRlcHRoSWR4LCBgbWF4KDAsIG1pbihkZXB0aCwgJHtpbnB1dFNoYXBlW2RlcHRoSWR4XX0gLSAxKSlgKX07XG4gICAgICAke2lucHV0LmluZGljZXNTZXQoJ2lucHV0X2luZGljZXMnLCBoZWlnaHRJZHgsIGBtYXgoMCwgbWluKGhlaWdodCwgJHtpbnB1dFNoYXBlW2hlaWdodElkeF19IC0gMSkpYCl9O1xuICAgICAgJHtpbnB1dC5pbmRpY2VzU2V0KCdpbnB1dF9pbmRpY2VzJywgd2lkdGhJZHgsIGBtYXgoMCwgbWluKHdpZHRoLCAke2lucHV0U2hhcGVbd2lkdGhJZHhdfSAtIDEpKWApfTtcbiAgICAgICR7c2V0Q2hhbm5lbEFuZEJhdGNoSW5kaWNlcyhpbnB1dCwgY2hhbm5lbElkeCwgYmF0Y2hJZHgsIDMpfVxuICAgICAgcmV0dXJuICR7aW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJyl9O1xuICAgIH1cblxuICAgIGZuIHRyaWxpbmVhckludGVycG9sYXRpb24ob3V0cHV0X2luZGljZXM6ICR7b3V0cHV0LnR5cGUuaW5kaWNlc30pIC0+ICR7ZFR5cGV9IHtcbiAgICAgIHZhciBvcmlnaW5hbEluZGljZXMgPSBjYWxjdWxhdGVPcmlnaW5hbEluZGljZXNGcm9tT3V0cHV0SW5kaWNlcyhvdXRwdXRfaW5kaWNlcyk7XG4gICAgICB2YXIgZGVwdGg6JHtkVHlwZX0gPSBvcmlnaW5hbEluZGljZXNbJHtkZXB0aElkeH1dO1xuICAgICAgdmFyIGhlaWdodDoke2RUeXBlfSA9IG9yaWdpbmFsSW5kaWNlc1ske2hlaWdodElkeH1dO1xuICAgICAgdmFyIHdpZHRoOiR7ZFR5cGV9ID0gb3JpZ2luYWxJbmRpY2VzWyR7d2lkdGhJZHh9XTtcbiAgICAgICR7XG4gICAgICAgIHVzZUV4dHJhcG9sYXRpb25cbiAgICAgICAgICA/IGBpZiAoZGVwdGggPCAwIHx8IGRlcHRoID4gKCR7aW5wdXRTaGFwZVtkZXB0aElkeF19IC0gMSkgfHwgaGVpZ2h0IDwgMCB8fCBoZWlnaHQgPiAoJHtcbiAgICAgICAgICAgICAgaW5wdXRTaGFwZVtoZWlnaHRJZHhdXG4gICAgICAgICAgICB9IC0gMSkgfHwgd2lkdGggPCAwIHx8ICh3aWR0aCA+ICR7aW5wdXRTaGFwZVt3aWR0aElkeF19IC0gMSkpIHtcbiAgICAgIHJldHVybiAke2V4dHJhcG9sYXRpb25WYWx1ZX07XG4gICAgICAgIH1gXG4gICAgICAgICAgOiAnJ1xuICAgICAgfTtcblxuICAgIGRlcHRoID0gbWF4KDAsIG1pbihkZXB0aCwgJHtpbnB1dFNoYXBlW2RlcHRoSWR4XX0gLSAxKSk7XG4gICAgICBoZWlnaHQgPSBtYXgoMCwgbWluKGhlaWdodCwgJHtpbnB1dFNoYXBlW2hlaWdodElkeF19IC0gMSkpO1xuICAgICAgd2lkdGggPSBtYXgoMCwgbWluKHdpZHRoLCAke2lucHV0U2hhcGVbd2lkdGhJZHhdfSAtIDEpKTtcbiAgICAgIHZhciBkZXB0aDE6IHUzMiA9IHUzMihkZXB0aCk7XG4gICAgICB2YXIgaGVpZ2h0MTogdTMyID0gdTMyKGhlaWdodCk7XG4gICAgICB2YXIgd2lkdGgxOiB1MzIgPSB1MzIod2lkdGgpO1xuICAgICAgdmFyIGRlcHRoMjogdTMyID0gdTMyKGRlcHRoICsgMSk7XG4gICAgICB2YXIgaGVpZ2h0MjogdTMyID0gdTMyKGhlaWdodCArIDEpO1xuICAgICAgdmFyIHdpZHRoMjogdTMyID0gdTMyKHdpZHRoICsgMSk7XG4gICAgICB2YXIgY2hhbm5lbDogdTMyID0gJHtpbnB1dFNoYXBlLmxlbmd0aCA+IDMgPyBgdTMyKG9yaWdpbmFsSW5kaWNlc1ske2NoYW5uZWxJZHh9XSlgIDogJzAnfTtcbiAgICAgIHZhciBiYXRjaDogdTMyID0gICR7aW5wdXRTaGFwZS5sZW5ndGggPiAzID8gYHUzMihvcmlnaW5hbEluZGljZXNbJHtiYXRjaElkeH1dKWAgOiAnMCd9O1xuXG4gICAgICB2YXIgeDExMTogJHtkVHlwZX0gPSBnZXRJbnB1dFZhbHVlKGJhdGNoLCBjaGFubmVsLCBkZXB0aDEsIGhlaWdodDEsIHdpZHRoMSk7XG4gICAgICB2YXIgeDExMjogJHtkVHlwZX0gPSBnZXRJbnB1dFZhbHVlKGJhdGNoLCBjaGFubmVsLCBkZXB0aDEsIGhlaWdodDEsIHdpZHRoMik7XG4gICAgICB2YXIgeDEyMTogJHtkVHlwZX0gPSBnZXRJbnB1dFZhbHVlKGJhdGNoLCBjaGFubmVsLCBkZXB0aDEsIGhlaWdodDIsIHdpZHRoMSk7XG4gICAgICB2YXIgeDEyMjogJHtkVHlwZX0gPSBnZXRJbnB1dFZhbHVlKGJhdGNoLCBjaGFubmVsLCBkZXB0aDEsIGhlaWdodDIsIHdpZHRoMik7XG4gICAgICB2YXIgeDIxMTogJHtkVHlwZX0gPSBnZXRJbnB1dFZhbHVlKGJhdGNoLCBjaGFubmVsLCBkZXB0aDIsIGhlaWdodDEsIHdpZHRoMSk7XG4gICAgICB2YXIgeDIxMjogJHtkVHlwZX0gPSBnZXRJbnB1dFZhbHVlKGJhdGNoLCBjaGFubmVsLCBkZXB0aDIsIGhlaWdodDEsIHdpZHRoMik7XG4gICAgICB2YXIgeDIyMTogJHtkVHlwZX0gPSBnZXRJbnB1dFZhbHVlKGJhdGNoLCBjaGFubmVsLCBkZXB0aDIsIGhlaWdodDIsIHdpZHRoMSk7XG4gICAgICB2YXIgeDIyMjogJHtkVHlwZX0gPSBnZXRJbnB1dFZhbHVlKGJhdGNoLCBjaGFubmVsLCBkZXB0aDIsIGhlaWdodDIsIHdpZHRoMik7XG4gICAgICB2YXIgZHgxOiAke2RUeXBlfSA9IGFicyhkZXB0aCAtICR7ZFR5cGV9KGRlcHRoMSkpO1xuICAgICAgdmFyIGR4MjogJHtkVHlwZX0gPSBhYnMoJHtkVHlwZX0oZGVwdGgyKSAtIGRlcHRoKTtcbiAgICAgIHZhciBkeTE6ICR7ZFR5cGV9ID0gYWJzKGhlaWdodCAtICR7ZFR5cGV9KGhlaWdodDEpKTtcbiAgICAgIHZhciBkeTI6ICR7ZFR5cGV9ID0gYWJzKCR7ZFR5cGV9KGhlaWdodDIpIC0gaGVpZ2h0KTtcbiAgICAgIHZhciBkejE6ICR7ZFR5cGV9ID0gYWJzKHdpZHRoIC0gJHtkVHlwZX0od2lkdGgxKSk7XG4gICAgICB2YXIgZHoyOiAke2RUeXBlfSA9IGFicygke2RUeXBlfSh3aWR0aDIpIC0gd2lkdGgpO1xuICAgICAgaWYgKGRlcHRoMSA9PSBkZXB0aDIpIHtcbiAgICAgICAgZHgxID0gMC41O1xuICAgICAgICBkeDIgPSAwLjU7XG4gICAgICB9XG4gICAgICBpZiAoaGVpZ2h0MSA9PSBoZWlnaHQyKSB7XG4gICAgICAgIGR5MSA9IDAuNTtcbiAgICAgICAgZHkyID0gMC41O1xuICAgICAgfVxuICAgICAgaWYgKHdpZHRoMSA9PSB3aWR0aDIpIHtcbiAgICAgICAgZHoxID0gMC41O1xuICAgICAgICBkejIgPSAwLjU7XG4gICAgICB9XG4gICAgICByZXR1cm4gKHgxMTEgKiBkeDIgKiBkeTIgKiBkejIgKyB4MTEyICogZHgyICogZHkyICogZHoxICsgeDEyMSAqIGR4MiAqIGR5MSAqZHoyICsgeDEyMiAqIGR4MiAqIGR5MSAqIGR6MSArXG4gICAgICAgICAgICAgIHgyMTEgKiBkeDEgKiBkeTIgKiBkejIgKyB4MjEyICogZHgxICogZHkyICogZHoxICsgeDIyMSAqIGR4MSAqIGR5MSAqZHoyICsgeDIyMiAqIGR4MSAqIGR5MSAqIGR6MSk7XG4gICAgfWA7XG59O1xuXG5jb25zdCBjcmVhdGVSZXNpemVQcm9ncmFtSW5mbyA9IChcbiAgaW5wdXRUZW5zb3I6IFRlbnNvclZpZXcsXG4gIGF0dHJpYnV0ZXM6IFJlc2l6ZUF0dHJpYnV0ZXMsXG4gIG9wc2V0VmVyc2lvbjogbnVtYmVyLFxuICBzY2FsZXNJbnB1dDogcmVhZG9ubHkgbnVtYmVyW10sXG4gIHNpemVzOiByZWFkb25seSBudW1iZXJbXSxcbiAgcm9pSW5wdXQ6IHJlYWRvbmx5IG51bWJlcltdLFxuKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRUZW5zb3IuZGltcztcbiAgY29uc3Qgcm9pID0gdXBkYXRlUm9JKHJvaUlucHV0LCBhdHRyaWJ1dGVzLmF4ZXMsIGlucHV0U2hhcGUubGVuZ3RoKTtcblxuICBsZXQgb3V0cHV0U2hhcGUgPSBpbml0T3V0cHV0U2hhcGUoaW5wdXRTaGFwZSwgc2NhbGVzSW5wdXQsIHNpemVzLCBhdHRyaWJ1dGVzLmF4ZXMpO1xuICBsZXQgc2NhbGVzID0gc2NhbGVzSW5wdXQuc2xpY2UoKTtcbiAgaWYgKHNjYWxlc0lucHV0Lmxlbmd0aCA9PT0gMCkge1xuICAgIHNjYWxlcyA9IGlucHV0U2hhcGUubWFwKCh2YWx1ZSwgaW5kZXgpID0+ICh2YWx1ZSA9PT0gMCA/IDEuMCA6IG91dHB1dFNoYXBlW2luZGV4XSAvIHZhbHVlKSk7XG4gICAgaWYgKGF0dHJpYnV0ZXMua2VlcEFzcGVjdFJhdGlvUG9saWN5ICE9PSAnc3RyZXRjaCcpIHtcbiAgICAgIG91dHB1dFNoYXBlID0gYWRqdXN0T3V0cHV0U2hhcGUoaW5wdXRTaGFwZSwgc2NhbGVzLCBhdHRyaWJ1dGVzKTtcbiAgICB9XG4gIH1cbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0VGVuc29yLmRhdGFUeXBlLCBvdXRwdXRTaGFwZS5sZW5ndGgpO1xuICBjb25zdCBpbnB1dCA9IGlucHV0VmFyaWFibGUoJ2lucHV0JywgaW5wdXRUZW5zb3IuZGF0YVR5cGUsIGlucHV0U2hhcGUubGVuZ3RoKTtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgY29uc3Qgbm9TY2FsZSA9IGlucHV0U2hhcGUubGVuZ3RoID09PSBvdXRwdXRTaGFwZS5sZW5ndGggJiYgaW5wdXRTaGFwZS5ldmVyeSgoZCwgaSkgPT4gZCA9PT0gb3V0cHV0U2hhcGVbaV0pO1xuICBjb25zdCB1c2VFeHRyYXBvbGF0aW9uID0gYXR0cmlidXRlcy5jb29yZGluYXRlVHJhbnNmb3JtTW9kZSA9PT0gJ3RmX2Nyb3BfYW5kX3Jlc2l6ZSc7XG4gIGNvbnN0IGV4dHJhcG9sYXRpb25WYWx1ZSA9IGF0dHJpYnV0ZXMuZXh0cmFwb2xhdGlvblZhbHVlO1xuICBjb25zdCBkYXRhVHlwZSA9IGlucHV0LnR5cGUudmFsdWU7XG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICAgICAgJHtcbiAgICAgICAgbm9TY2FsZVxuICAgICAgICAgID8gJydcbiAgICAgICAgICA6IGBcbiAgICAgICR7Z2V0T3JpZ2luYWxDb29yZGluYXRlRnJvbVJlc2l6ZWRDb29yZGluYXRlKGF0dHJpYnV0ZXMuY29vcmRpbmF0ZVRyYW5zZm9ybU1vZGUsIGRhdGFUeXBlKX07XG4gICAgICAkeygoKSA9PiB7XG4gICAgICAgIHN3aXRjaCAoYXR0cmlidXRlcy5tb2RlKSB7XG4gICAgICAgICAgY2FzZSAnbmVhcmVzdCc6XG4gICAgICAgICAgICByZXR1cm4gYFxuICAgICAgICAgICAgICAke2NoZWNrSW5wdXRJbmRpY2VzKGlucHV0LCBpbnB1dFNoYXBlKX07XG4gICAgICAgICAgICAgICR7Z2V0TmVhcmVzdFBpeGVsRnJvbU9yaWdpbmFsKGF0dHJpYnV0ZXMubmVhcmVzdE1vZGUsIG9wc2V0VmVyc2lvbiwgZGF0YVR5cGUpfTtcbiAgICAgICAgICAgICAgJHtjYWxjdWxhdGVJbnB1dEluZGljZXNGcm9tT3V0cHV0SW5kaWNlcyhcbiAgICAgICAgICAgICAgICBpbnB1dCxcbiAgICAgICAgICAgICAgICBvdXRwdXQsXG4gICAgICAgICAgICAgICAgaW5wdXRTaGFwZSxcbiAgICAgICAgICAgICAgICBvdXRwdXRTaGFwZSxcbiAgICAgICAgICAgICAgICBzY2FsZXMubGVuZ3RoLFxuICAgICAgICAgICAgICAgIHJvaS5sZW5ndGgsXG4gICAgICAgICAgICAgICAgdXNlRXh0cmFwb2xhdGlvbixcbiAgICAgICAgICAgICAgKX07XG4gICAgICAgICAgICAgIGA7XG4gICAgICAgICAgY2FzZSAnbGluZWFyJzpcbiAgICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICAgICR7Y2FsY3VsYXRlT3JpZ2luYWxJbmRpY2VzRnJvbU91dHB1dEluZGljZXMob3V0cHV0LCBpbnB1dFNoYXBlLCBvdXRwdXRTaGFwZSwgc2NhbGVzLmxlbmd0aCwgcm9pLmxlbmd0aCl9O1xuICAgICAgICAgICAgICAkeygoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGlucHV0U2hhcGUubGVuZ3RoID09PSAyIHx8IGlucHV0U2hhcGUubGVuZ3RoID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gYCR7YmlsaW5lYXJJbnRlcnBvbGF0aW9uKGlucHV0LCBvdXRwdXQsIGlucHV0U2hhcGUsIHVzZUV4dHJhcG9sYXRpb24sIGV4dHJhcG9sYXRpb25WYWx1ZSl9YDtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlucHV0U2hhcGUubGVuZ3RoID09PSAzIHx8IGlucHV0U2hhcGUubGVuZ3RoID09PSA1KSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gYCR7dHJpbGluZWFySW50ZXJwb2xhdGlvbihpbnB1dCwgb3V0cHV0LCBpbnB1dFNoYXBlLCB1c2VFeHRyYXBvbGF0aW9uLCBleHRyYXBvbGF0aW9uVmFsdWUpfWA7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHRocm93IEVycm9yKCdMaW5lYXIgbW9kZSBvbmx5IHN1cHBvcnRzIGlucHV0IGRpbXMgMiwgMywgNCBhbmQgNSBhcmUgc3VwcG9ydGVkIGluIGxpbmVhciBtb2RlLicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSkoKX07XG4gICAgICAgICAgICBgO1xuICAgICAgICAgIGNhc2UgJ2N1YmljJzpcbiAgICAgICAgICAgIHJldHVybiBgXG4gICAgICAgICAgICAkeygoKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChpbnB1dFNoYXBlLmxlbmd0aCA9PT0gMiB8fCBpbnB1dFNoYXBlLmxlbmd0aCA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBgJHtiaWN1YmljSW50ZXJwb2xhdGlvbihcbiAgICAgICAgICAgICAgICAgIGlucHV0LFxuICAgICAgICAgICAgICAgICAgb3V0cHV0LFxuICAgICAgICAgICAgICAgICAgaW5wdXRTaGFwZSxcbiAgICAgICAgICAgICAgICAgIG91dHB1dFNoYXBlLFxuICAgICAgICAgICAgICAgICAgc2NhbGVzLFxuICAgICAgICAgICAgICAgICAgcm9pLFxuICAgICAgICAgICAgICAgICAgYXR0cmlidXRlcy5jdWJpY0NvZWZmQSxcbiAgICAgICAgICAgICAgICAgIHVzZUV4dHJhcG9sYXRpb24sXG4gICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzLmV4dHJhcG9sYXRpb25WYWx1ZSxcbiAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXMuZXhjbHVkZU91dHNpZGUsXG4gICAgICAgICAgICAgICAgKX1gO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IEVycm9yKCdDdWJpYyBtb2RlIG9ubHkgc3VwcG9ydHMgaW5wdXQgZGltcyAyIGFuZCA0IGFyZSBzdXBwb3J0ZWQgaW4gbGluZWFyIG1vZGUuJyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKCl9O1xuICAgICAgICAgICAgYDtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgRXJyb3IoJ0ludmFsaWQgcmVzaXplIG1vZGUnKTtcbiAgICAgICAgfVxuICAgICAgfSkoKX07XG4gICAgICBgXG4gICAgICB9XG4gICAgICAke3NoYWRlckhlbHBlclxuICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdvdXRwdXRfc2l6ZScsICd1MzInKVxuICAgICAgICAucmVnaXN0ZXJVbmlmb3JtKCdzY2FsZXMnLCAnZjMyJywgc2NhbGVzLmxlbmd0aClcbiAgICAgICAgLnJlZ2lzdGVyVW5pZm9ybSgncm9pJywgJ2YzMicsIHJvaS5sZW5ndGgpXG4gICAgICAgIC5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBvdXRwdXQpfVxuICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dF9zaXplJyl9XG4gICAgICAgICR7XG4gICAgICAgICAgbm9TY2FsZVxuICAgICAgICAgICAgPyAnb3V0cHV0W2dsb2JhbF9pZHhdID0gaW5wdXRbZ2xvYmFsX2lkeF07J1xuICAgICAgICAgICAgOiBgXG4gICAgICAgIGxldCBvdXRwdXRfaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcbiAgICAgICAgdmFyIGlucHV0X2luZGljZXM6ICR7aW5wdXQudHlwZS5pbmRpY2VzfTtcbiAgICAgICAgJHsoKCkgPT4ge1xuICAgICAgICAgIHN3aXRjaCAoYXR0cmlidXRlcy5tb2RlKSB7XG4gICAgICAgICAgICBjYXNlICduZWFyZXN0JzpcbiAgICAgICAgICAgICAgcmV0dXJuIGBpbnB1dF9pbmRpY2VzID0gY2FsY3VsYXRlSW5wdXRJbmRpY2VzRnJvbU91dHB1dEluZGljZXMob3V0cHV0X2luZGljZXMpO1xuICAgICAgICAgICAgICAgIGlmIChjaGVja0lucHV0SW5kaWNlcyhpbnB1dF9pbmRpY2VzKSkge1xuICAgICAgICAgICAgICAgICAgb3V0cHV0W2dsb2JhbF9pZHhdID0gJHtpbnB1dC5nZXRCeUluZGljZXMoJ2lucHV0X2luZGljZXMnKX07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIG91dHB1dFtnbG9iYWxfaWR4XSA9ICR7YXR0cmlidXRlcy5leHRyYXBvbGF0aW9uVmFsdWV9O1xuICAgICAgICAgICAgICAgIH1gO1xuICAgICAgICAgICAgY2FzZSAnbGluZWFyJzpcbiAgICAgICAgICAgICAgcmV0dXJuIGBvdXRwdXRbZ2xvYmFsX2lkeF0gPSAke1xuICAgICAgICAgICAgICAgIGlucHV0U2hhcGUubGVuZ3RoID09PSAyIHx8IGlucHV0U2hhcGUubGVuZ3RoID09PSA0ID8gJ2JpbGluZWFySW50ZXJwb2xhdGlvbicgOiAndHJpbGluZWFySW50ZXJwb2xhdGlvbidcbiAgICAgICAgICAgICAgfShvdXRwdXRfaW5kaWNlcyk7YDtcbiAgICAgICAgICAgIGNhc2UgJ2N1YmljJzpcbiAgICAgICAgICAgICAgcmV0dXJuICdvdXRwdXRbZ2xvYmFsX2lkeF0gPSBiaWN1YmljSW50ZXJwb2xhdGlvbihvdXRwdXRfaW5kaWNlcyk7JztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIHRocm93IEVycm9yKGBVbnN1cHBvcnRlZCByZXNpemUgbW9kZTogJHthdHRyaWJ1dGVzLm1vZGV9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpfTtcbmBcbiAgICAgICAgfVxuICAgICAgfWA7XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnUmVzaXplJyxcbiAgICBzaGFkZXJDYWNoZToge1xuICAgICAgaGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX18JHtvcHNldFZlcnNpb259fCR7XG4gICAgICAgIHNjYWxlcy5sZW5ndGggPiAwID8gKGF0dHJpYnV0ZXMubW9kZSA9PT0gJ2N1YmljJyA/IHNjYWxlcyA6IHNjYWxlcy5sZW5ndGgpIDogJydcbiAgICAgIH18JHtzaXplcy5sZW5ndGggPiAwID8gc2l6ZXMgOiAnJ318JHtyb2kubGVuZ3RoID4gMCA/IHJvaSA6ICcnfXwke25vU2NhbGV9fCR7XG4gICAgICAgIGF0dHJpYnV0ZXMubW9kZSA9PT0gJ25lYXJlc3QnID8gaW5wdXRTaGFwZS5sZW5ndGggOiBpbnB1dFNoYXBlXG4gICAgICB9YCxcbiAgICAgIGlucHV0RGVwZW5kZW5jaWVzOiBbJ3JhbmsnXSxcbiAgICB9LFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICBnZXRSdW5EYXRhOiAoKSA9PiAoe1xuICAgICAgb3V0cHV0czogW3sgZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dFRlbnNvci5kYXRhVHlwZSB9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IHsgeDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLmZsb2F0LCBkYXRhOiBzY2FsZXMgfSxcbiAgICAgICAgeyB0eXBlOiBEYXRhVHlwZS5mbG9hdCwgZGF0YTogcm9pIH0sXG4gICAgICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0U2hhcGUsIG91dHB1dFNoYXBlKSxcbiAgICAgIF0sXG4gICAgfSksXG4gIH07XG59O1xuXG5jb25zdCBnZXRPcHNldFZlcnNpb25Gcm9tQ3VzdG9tRGF0YUJ1ZmZlciA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IG51bWJlciA9PiB7XG4gIGNvbnN0IGN1c3RvbURhdGFCdWZmZXIgPSBjb250ZXh0LmN1c3RvbURhdGFCdWZmZXI7XG4gIGNvbnN0IGN1c3RvbURhdGFCdWZmZXIzMiA9IG5ldyBVaW50MzJBcnJheShjdXN0b21EYXRhQnVmZmVyLCBjdXN0b21EYXRhQnVmZmVyLmJ5dGVPZmZzZXQsIDEpO1xuICBjb25zdCBvcHNldFZlcnNpb24gPSBjdXN0b21EYXRhQnVmZmVyMzJbMF07XG4gIHJldHVybiBvcHNldFZlcnNpb247XG59O1xuXG5leHBvcnQgY29uc3QgcmVzaXplID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBSZXNpemVBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnN0IHNjYWxlczogbnVtYmVyW10gPSBbXTtcbiAgY29uc3Qgc2l6ZXM6IG51bWJlcltdID0gW107XG4gIGNvbnN0IHJvaTogbnVtYmVyW10gPSBbXTtcblxuICAvLyBOb3RlIHRoYXQgc2NhbGVzIGluIHJlc2l6ZSBhcmUgYWx3YXlzIGYzMi4gcm9pIGNhbiBiZSBmMzIgb3IgZjE2LlxuICAvLyBUT0RPOiBDdXJyZW50bHkgdGhpcyBjb2RlIGRvZXMgbm90IHN1cHBvcnQgZjE2IGZvciByb2kgd2hlbiBwYXNzZWQgYXMgb3B0aW9uYWwgaW5wdXQuXG5cbiAgY29uc3Qgb3BzZXRWZXJzaW9uID0gZ2V0T3BzZXRWZXJzaW9uRnJvbUN1c3RvbURhdGFCdWZmZXIoY29udGV4dCk7XG4gIGlmIChhdHRyaWJ1dGVzLmFudGlhbGlhcyAhPT0gMCkge1xuICAgIHRocm93IEVycm9yKCdPbmx5IGRlZmF1bHQgdmFsdWUgKDApIGZvciBBbnRpYWxpYXMgYXR0cmlidXRlIGlzIHN1cHBvcnRlZCcpO1xuICB9XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzLCBvcHNldFZlcnNpb24sIHNjYWxlcywgc2l6ZXMsIHJvaSk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVSZXNpemVQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0c1swXSwgYXR0cmlidXRlcywgb3BzZXRWZXJzaW9uLCBzY2FsZXMsIHNpemVzLCByb2kpLCB7XG4gICAgaW5wdXRzOiBbMF0sXG4gIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlUmVzaXplQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFJlc2l6ZUF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBhbnRpYWxpYXMgPSBhdHRyaWJ1dGVzLmFudGlhbGlhcyBhcyBudW1iZXI7XG4gIGNvbnN0IGF4ZXMgPSBhdHRyaWJ1dGVzLmF4ZXMgYXMgbnVtYmVyW107XG4gIGNvbnN0IGNvb3JkaW5hdGVUcmFuc2Zvcm1Nb2RlOiBDb29yZGluYXRlVHJhbnNmb3JtTW9kZSA9XG4gICAgYXR0cmlidXRlcy5jb29yZGluYXRlVHJhbnNmb3JtTW9kZSBhcyBDb29yZGluYXRlVHJhbnNmb3JtTW9kZTtcbiAgY29uc3QgY3ViaWNDb2VmZkEgPSBhdHRyaWJ1dGVzLmN1YmljQ29lZmZBIGFzIG51bWJlcjtcbiAgY29uc3QgZXhjbHVkZU91dHNpZGUgPSAoYXR0cmlidXRlcy5leGNsdWRlT3V0c2lkZSBhcyBudW1iZXIpICE9PSAwO1xuICBjb25zdCBleHRyYXBvbGF0aW9uVmFsdWUgPSBhdHRyaWJ1dGVzLmV4dHJhcG9sYXRpb25WYWx1ZSBhcyBudW1iZXI7XG4gIGNvbnN0IGtlZXBBc3BlY3RSYXRpb1BvbGljeTogS2VlcEFzcGVjdFJhdGlvUG9saWN5ID0gYXR0cmlidXRlcy5rZWVwQXNwZWN0UmF0aW9Qb2xpY3kgYXMgS2VlcEFzcGVjdFJhdGlvUG9saWN5O1xuICBjb25zdCBtb2RlOiBNb2RlID0gYXR0cmlidXRlcy5tb2RlIGFzIE1vZGU7XG4gIC8vIElmIG5lYXJlc3RNb2RlIGlzIG5vdCBzcGVjaWZpZWQsIHVzZSBzaW1wbGUgbW9kZS5cbiAgY29uc3QgbmVhcmVzdE1vZGU6IE5lYXJlc3RNb2RlID0gKGF0dHJpYnV0ZXMubmVhcmVzdE1vZGUgPT09ICcnID8gJ3NpbXBsZScgOiBhdHRyaWJ1dGVzLm5lYXJlc3RNb2RlKSBhcyBOZWFyZXN0TW9kZTtcbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7XG4gICAgYW50aWFsaWFzLFxuICAgIGF4ZXMsXG4gICAgY29vcmRpbmF0ZVRyYW5zZm9ybU1vZGUsXG4gICAgY3ViaWNDb2VmZkEsXG4gICAgZXhjbHVkZU91dHNpZGUsXG4gICAgZXh0cmFwb2xhdGlvblZhbHVlLFxuICAgIGtlZXBBc3BlY3RSYXRpb1BvbGljeSxcbiAgICBtb2RlLFxuICAgIG5lYXJlc3RNb2RlLFxuICB9KTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY2FzdFRvRjMyLFxuICBnZXRNYXhDb21wb25lbnRzLFxuICBpbnB1dFZhcmlhYmxlLFxuICBvdXRwdXRWYXJpYWJsZSxcbiAgU2hhZGVySGVscGVyLFxuICBzdW1WZWN0b3IsXG4gIHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZSxcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBTa2lwTGF5ZXJOb3JtQXR0cmlidXRlcyB7XG4gIHNpbXBsaWZpZWQ6IGJvb2xlYW47XG4gIGVwc2lsb246IG51bWJlcjtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCA8IDMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2xheWVyTm9ybSByZXF1aXJlcyBhdCBsZWFzdCAzIGlucHV0cy4nKTtcbiAgfVxuXG4gIGNvbnN0IGlucHV0OiBUZW5zb3JWaWV3ID0gaW5wdXRzWzBdO1xuICBjb25zdCBza2lwOiBUZW5zb3JWaWV3ID0gaW5wdXRzWzFdO1xuICBjb25zdCBnYW1tYTogVGVuc29yVmlldyA9IGlucHV0c1syXTtcblxuICBpZiAoaW5wdXQuZGF0YVR5cGUgIT09IHNraXAuZGF0YVR5cGUgfHwgaW5wdXQuZGF0YVR5cGUgIT09IGdhbW1hLmRhdGFUeXBlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdBbGwgaW5wdXRzIG11c3QgaGF2ZSB0aGUgc2FtZSBkYXRhIHR5cGUnKTtcbiAgfVxuXG4gIGlmIChpbnB1dC5kaW1zLmxlbmd0aCAhPT0gMyAmJiBpbnB1dC5kaW1zLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgbXVzdCBiZSAyRCBvciAzRCcpO1xuICB9XG5cbiAgaWYgKHNraXAuZGltcy5sZW5ndGggIT09IDMgJiYgc2tpcC5kaW1zLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignU2tpcCBtdXN0IGJlIDJEIG9yIDNEJyk7XG4gIH1cblxuICBjb25zdCBoaWRkZW5TaXplID0gaW5wdXQuZGltc1tpbnB1dC5kaW1zLmxlbmd0aCAtIDFdO1xuICBjb25zdCBzZXF1ZW5jZUxlbmd0aCA9IGlucHV0LmRpbXNbaW5wdXQuZGltcy5sZW5ndGggLSAyXTtcbiAgaWYgKHNraXAuZGltc1tza2lwLmRpbXMubGVuZ3RoIC0gMV0gIT09IGhpZGRlblNpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1NraXAgbXVzdCBoYXZlIHRoZSBzYW1lIGhpZGRlbiBzaXplIGFzIGlucHV0Jyk7XG4gIH1cbiAgaWYgKHNraXAuZGltc1tza2lwLmRpbXMubGVuZ3RoIC0gMl0gIT09IHNlcXVlbmNlTGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdTa2lwIG11c3QgaGF2ZSB0aGUgc2FtZSBzZXF1ZW5jZSBsZW5ndGggYXMgaW5wdXQnKTtcbiAgfVxuXG4gIGlmIChnYW1tYS5kaW1zLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignR2FtbWEgbXVzdCBiZSAxRCcpO1xuICB9XG4gIGlmIChnYW1tYS5kaW1zW2dhbW1hLmRpbXMubGVuZ3RoIC0gMV0gIT09IGhpZGRlblNpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0dhbW1hIG11c3QgaGF2ZSB0aGUgc2FtZSBoaWRkZW4gc2l6ZSBhcyBpbnB1dCcpO1xuICB9XG4gIGlmIChpbnB1dHMubGVuZ3RoID4gMykge1xuICAgIGNvbnN0IGJldGE6IFRlbnNvclZpZXcgPSBpbnB1dHNbM107XG4gICAgaWYgKGJldGEuZGltcy5sZW5ndGggIT09IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQmV0YSBtdXN0IGJlIDFEJyk7XG4gICAgfVxuICAgIGlmIChiZXRhLmRpbXNbYmV0YS5kaW1zLmxlbmd0aCAtIDFdICE9PSBoaWRkZW5TaXplKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0JldGEgbXVzdCBoYXZlIHRoZSBzYW1lIGhpZGRlbiBzaXplIGFzIGlucHV0Jyk7XG4gICAgfVxuICB9XG4gIGlmIChpbnB1dHMubGVuZ3RoID4gNCkge1xuICAgIGNvbnN0IGJpYXM6IFRlbnNvclZpZXcgPSBpbnB1dHNbNF07XG4gICAgaWYgKGJpYXMuZGltcy5sZW5ndGggIT09IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQmlhcyBtdXN0IGJlIDFEJyk7XG4gICAgfVxuICAgIGlmIChiaWFzLmRpbXNbYmlhcy5kaW1zLmxlbmd0aCAtIDFdICE9PSBoaWRkZW5TaXplKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0JpYXMgbXVzdCBoYXZlIHRoZSBzYW1lIGhpZGRlbiBzaXplIGFzIGlucHV0Jyk7XG4gICAgfVxuICB9XG59O1xuXG5jb25zdCBjcmVhdGVTa2lwTGF5ZXJOb3JtUHJvZ3JhbUluZm8gPSAoXG4gIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBhdHRyaWJ1dGVzOiBTa2lwTGF5ZXJOb3JtQXR0cmlidXRlcyxcbiAgb3V0cHV0Q291bnQ6IG51bWJlcixcbiAgaXNUcmFpbmluZzogYm9vbGVhbixcbik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3Qgc2ltcGxpZmllZCA9IGF0dHJpYnV0ZXMuc2ltcGxpZmllZDtcblxuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGlucHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKGlucHV0U2hhcGUpO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IGlucHV0U2hhcGU7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBpbnB1dFNpemU7XG4gIGNvbnN0IGhpZGRlblNpemUgPSBpbnB1dFNoYXBlLnNsaWNlKC0xKVswXTtcbiAgY29uc3QgbWVhbkludlN0ZERldkRpbSA9IGlzVHJhaW5pbmcgPyBpbnB1dFNoYXBlLnNsaWNlKDAsIC0xKS5jb25jYXQoMSkgOiBbXTtcbiAgY29uc3QgaGFzQmV0YUlucHV0ID0gIXNpbXBsaWZpZWQgJiYgaW5wdXRzLmxlbmd0aCA+IDM7XG4gIGNvbnN0IGhhc0JpYXNJbnB1dCA9IGlucHV0cy5sZW5ndGggPiA0O1xuICBjb25zdCBoYXNNZWFuT3V0cHV0ID0gaXNUcmFpbmluZyAmJiBvdXRwdXRDb3VudCA+IDE7XG4gIGNvbnN0IGhhc0ludlN0ZERldk91dHB1dCA9IGlzVHJhaW5pbmcgJiYgb3V0cHV0Q291bnQgPiAyO1xuICBjb25zdCBoYXNJbnB1dFNraXBCaWFzU3VtT3V0cHV0ID0gb3V0cHV0Q291bnQgPiAzO1xuICBjb25zdCB3b3JrZ3JvdXBTaXplID0gNjQ7XG5cbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoaGlkZGVuU2l6ZSk7XG5cbiAgY29uc3QgcHJvZ3JhbVVuaWZvcm1zOiBQcm9ncmFtVW5pZm9ybVtdID0gW1xuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgeyB0eXBlOiBEYXRhVHlwZS51aW50MzIsIGRhdGE6IGNvbXBvbmVudHMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogaGlkZGVuU2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUuZmxvYXQsIGRhdGE6IGF0dHJpYnV0ZXMuZXBzaWxvbiB9LFxuICBdO1xuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IHtcbiAgICBjb25zdCB1bmlmb3Jtc0FycmF5OiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICAgIHsgbmFtZTogJ291dHB1dF9zaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICAgIHsgbmFtZTogJ2NvbXBvbmVudHMnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnaGlkZGVuX3NpemUnLCB0eXBlOiAndTMyJyB9LFxuICAgICAgeyBuYW1lOiAnZXBzaWxvbicsIHR5cGU6ICdmMzInIH0sXG4gICAgXTtcbiAgICBjb25zdCB2YXJpYWJsZXMgPSBbXG4gICAgICBpbnB1dFZhcmlhYmxlKCd4JywgaW5wdXRzWzBdLmRhdGFUeXBlLCBpbnB1dHNbMF0uZGltcywgY29tcG9uZW50cyksXG4gICAgICBpbnB1dFZhcmlhYmxlKCdza2lwJywgaW5wdXRzWzFdLmRhdGFUeXBlLCBpbnB1dHNbMV0uZGltcywgY29tcG9uZW50cyksXG4gICAgICBpbnB1dFZhcmlhYmxlKCdnYW1tYScsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMsIGNvbXBvbmVudHMpLFxuICAgIF07XG4gICAgaWYgKGhhc0JldGFJbnB1dCkge1xuICAgICAgdmFyaWFibGVzLnB1c2goaW5wdXRWYXJpYWJsZSgnYmV0YScsIGlucHV0c1szXS5kYXRhVHlwZSwgaW5wdXRzWzNdLmRpbXMsIGNvbXBvbmVudHMpKTtcbiAgICB9XG4gICAgaWYgKGhhc0JpYXNJbnB1dCkge1xuICAgICAgdmFyaWFibGVzLnB1c2goaW5wdXRWYXJpYWJsZSgnYmlhcycsIGlucHV0c1s0XS5kYXRhVHlwZSwgaW5wdXRzWzRdLmRpbXMsIGNvbXBvbmVudHMpKTtcbiAgICB9XG4gICAgdmFyaWFibGVzLnB1c2gob3V0cHV0VmFyaWFibGUoJ291dHB1dCcsIGlucHV0c1swXS5kYXRhVHlwZSwgb3V0cHV0U2hhcGUsIGNvbXBvbmVudHMpKTtcbiAgICBpZiAoaGFzTWVhbk91dHB1dCkge1xuICAgICAgdmFyaWFibGVzLnB1c2gob3V0cHV0VmFyaWFibGUoJ21lYW5fb3V0cHV0JywgRGF0YVR5cGUuZmxvYXQsIG1lYW5JbnZTdGREZXZEaW0pKTtcbiAgICB9XG4gICAgaWYgKGhhc0ludlN0ZERldk91dHB1dCkge1xuICAgICAgdmFyaWFibGVzLnB1c2gob3V0cHV0VmFyaWFibGUoJ2ludl9zdGRfb3V0cHV0JywgRGF0YVR5cGUuZmxvYXQsIG1lYW5JbnZTdGREZXZEaW0pKTtcbiAgICB9XG4gICAgaWYgKGhhc0lucHV0U2tpcEJpYXNTdW1PdXRwdXQpIHtcbiAgICAgIHZhcmlhYmxlcy5wdXNoKG91dHB1dFZhcmlhYmxlKCdpbnB1dF9za2lwX2JpYXNfc3VtJywgaW5wdXRzWzBdLmRhdGFUeXBlLCBvdXRwdXRTaGFwZSwgY29tcG9uZW50cykpO1xuICAgIH1cbiAgICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclR5cGVUb1dzZ2xTdG9yYWdlVHlwZShpbnB1dHNbMF0uZGF0YVR5cGUpO1xuICAgIGNvbnN0IHZlY0RhdGFUeXBlID0gdGVuc29yVHlwZVRvV3NnbFN0b3JhZ2VUeXBlKERhdGFUeXBlLmZsb2F0LCBjb21wb25lbnRzKTtcbiAgICByZXR1cm4gYFxuXG4gICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zQXJyYXkpLmRlY2xhcmVWYXJpYWJsZXMoLi4udmFyaWFibGVzKX1cbiAgICAgIHZhcjx3b3JrZ3JvdXA+IHN1bV9zaGFyZWQgOiBhcnJheTwke3ZlY0RhdGFUeXBlfSwgJHt3b3JrZ3JvdXBTaXplfT47XG4gICAgICB2YXI8d29ya2dyb3VwPiBzdW1fc3F1YXJlZF9zaGFyZWQgOiBhcnJheTwke3ZlY0RhdGFUeXBlfSwgJHt3b3JrZ3JvdXBTaXplfT47XG5cbiAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydChbd29ya2dyb3VwU2l6ZSwgMSwgMV0pfVxuICAgICAgICBsZXQgaXggPSBsb2NhbF9pZC54O1xuICAgICAgICBsZXQgaXkgPSBnbG9iYWxfaWQueCAvICR7d29ya2dyb3VwU2l6ZX07XG5cbiAgICAgICAgbGV0IGhpZGRlbl9zaXplX3ZlY3Rvcml6ZWQ6IHUzMiA9IHVuaWZvcm1zLmhpZGRlbl9zaXplIC8gdW5pZm9ybXMuY29tcG9uZW50cztcbiAgICAgICAgdmFyIHN0cmlkZSA9IGhpZGRlbl9zaXplX3ZlY3Rvcml6ZWQgLyAke3dvcmtncm91cFNpemV9O1xuICAgICAgICBsZXQgb2Zmc2V0ID0gaXggKiBzdHJpZGUgKyBpeSAqIGhpZGRlbl9zaXplX3ZlY3Rvcml6ZWQ7XG4gICAgICAgIGxldCBvZmZzZXQxZCA9IHN0cmlkZSAqIGl4O1xuICAgICAgICBpZiAoaXggPT0gJHt3b3JrZ3JvdXBTaXplIC0gMX0pIHtcbiAgICAgICAgICBzdHJpZGUgPSBoaWRkZW5fc2l6ZV92ZWN0b3JpemVkIC0gc3RyaWRlICogaXg7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgaTogdTMyID0gMDsgaSA8IHN0cmlkZTsgaSsrKSB7XG4gICAgICAgICAgbGV0IHNraXBfdmFsdWUgPSBza2lwW29mZnNldCArIGldO1xuICAgICAgICAgIGxldCBiaWFzX3ZhbHVlID0gJHtoYXNCaWFzSW5wdXQgPyAnYmlhc1tvZmZzZXQxZCArIGldJyA6IGRhdGFUeXBlICsgJygwLjApJ307XG4gICAgICAgICAgbGV0IGlucHV0X3ZhbHVlID0geFtvZmZzZXQgKyBpXTtcbiAgICAgICAgICBsZXQgdmFsdWUgPSBpbnB1dF92YWx1ZSArIHNraXBfdmFsdWUgKyBiaWFzX3ZhbHVlO1xuICAgICAgICAgICR7aGFzSW5wdXRTa2lwQmlhc1N1bU91dHB1dCA/ICdpbnB1dF9za2lwX2JpYXNfc3VtW29mZnNldCArIGldID0gdmFsdWU7JyA6ICcnfVxuICAgICAgICAgIG91dHB1dFtvZmZzZXQgKyBpXSA9IHZhbHVlO1xuICAgICAgICAgIGxldCBmMzJfdmFsdWUgPSAke2Nhc3RUb0YzMihkYXRhVHlwZSwgY29tcG9uZW50cywgJ3ZhbHVlJyl9O1xuICAgICAgICAgIHN1bV9zaGFyZWRbaXhdICs9IGYzMl92YWx1ZTtcbiAgICAgICAgICBzdW1fc3F1YXJlZF9zaGFyZWRbaXhdICs9IGYzMl92YWx1ZSAqIGYzMl92YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgICAgdmFyIHJlZHVjZV9zaXplIDogdTMyID0gJHt3b3JrZ3JvdXBTaXplfTtcbiAgICAgICAgZm9yICh2YXIgY3Vycl9zaXplID0gcmVkdWNlX3NpemUgPj4gMTsgIGN1cnJfc2l6ZSA+IDA7IGN1cnJfc2l6ZSA9IHJlZHVjZV9zaXplID4+IDEpIHtcbiAgICAgICAgICByZWR1Y2Vfc2l6ZSA9IGN1cnJfc2l6ZSArIChyZWR1Y2Vfc2l6ZSAmIDEpO1xuICAgICAgICAgIGlmIChpeCA8IGN1cnJfc2l6ZSkge1xuICAgICAgICAgICAgc3VtX3NoYXJlZFtpeF0gKz0gc3VtX3NoYXJlZFtpeCArIHJlZHVjZV9zaXplXTtcbiAgICAgICAgICAgIHN1bV9zcXVhcmVkX3NoYXJlZFtpeF0gKz0gc3VtX3NxdWFyZWRfc2hhcmVkW2l4ICsgcmVkdWNlX3NpemVdO1xuICAgICAgICAgIH1cbiAgICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgc3VtID0gc3VtX3NoYXJlZFswXTtcbiAgICAgICAgbGV0IHNxdWFyZV9zdW0gPSBzdW1fc3F1YXJlZF9zaGFyZWRbMF07XG4gICAgICAgIGxldCBtZWFuID0gJHtzdW1WZWN0b3IoJ3N1bScsIGNvbXBvbmVudHMpfSAvIGYzMih1bmlmb3Jtcy5oaWRkZW5fc2l6ZSk7XG4gICAgICAgIGxldCBpbnZfc3RkX2RldiA9IGludmVyc2VTcXJ0KCR7c3VtVmVjdG9yKCdzcXVhcmVfc3VtJywgY29tcG9uZW50cyl9IC8gZjMyKHVuaWZvcm1zLmhpZGRlbl9zaXplKSAke1xuICAgICAgICAgIHNpbXBsaWZpZWQgPyAnJyA6ICctIG1lYW4gKiBtZWFuJ1xuICAgICAgICB9ICsgdW5pZm9ybXMuZXBzaWxvbik7XG4gICAgICAgICR7aGFzTWVhbk91dHB1dCA/ICdtZWFuX291dHB1dFtnbG9iYWxfaWR4XSA9IG1lYW47JyA6ICcnfVxuICAgICAgICAke2hhc0ludlN0ZERldk91dHB1dCA/ICdpbnZfc3RkX291dHB1dFtnbG9iYWxfaWR4XSA9IGludl9zdGRfZGV2OycgOiAnJ31cblxuICAgICAgICBmb3IgKHZhciBpOiB1MzIgPSAwOyBpIDwgc3RyaWRlOyBpKyspIHtcbiAgICAgICAgICBvdXRwdXRbb2Zmc2V0ICsgaV0gPSAob3V0cHV0W29mZnNldCArIGldICR7c2ltcGxpZmllZCA/ICcnIDogYC0gJHtkYXRhVHlwZX0obWVhbilgfSkgKlxuICAgICAgICAgICAgJHtkYXRhVHlwZX0oaW52X3N0ZF9kZXYpICogZ2FtbWFbb2Zmc2V0MWQgKyBpXVxuICAgICAgICAgICAgJHtoYXNCZXRhSW5wdXQgPyAnKyBiZXRhW29mZnNldDFkICsgaV0nIDogJyd9O1xuICAgICAgICB9XG4gICAgICB9YDtcbiAgfTtcbiAgY29uc3Qgb3V0cHV0cyA9IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dO1xuICBpZiAob3V0cHV0Q291bnQgPiAxKSB7XG4gICAgb3V0cHV0cy5wdXNoKHsgZGltczogbWVhbkludlN0ZERldkRpbSwgZGF0YVR5cGU6IERhdGFUeXBlLmZsb2F0IH0pO1xuICB9XG4gIGlmIChvdXRwdXRDb3VudCA+IDIpIHtcbiAgICBvdXRwdXRzLnB1c2goeyBkaW1zOiBtZWFuSW52U3RkRGV2RGltLCBkYXRhVHlwZTogRGF0YVR5cGUuZmxvYXQgfSk7XG4gIH1cbiAgaWYgKG91dHB1dENvdW50ID4gMykge1xuICAgIG91dHB1dHMucHVzaCh7IGRpbXM6IGlucHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUgfSk7XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnU2tpcExheWVyTm9ybWFsaXphdGlvbicsXG4gICAgc2hhZGVyQ2FjaGU6IHtcbiAgICAgIGhpbnQ6IGAke2NvbXBvbmVudHN9OyR7aGFzTWVhbk91dHB1dH07JHtoYXNJbnZTdGREZXZPdXRwdXR9OyR7aGFzSW5wdXRTa2lwQmlhc1N1bU91dHB1dH1gLFxuICAgICAgaW5wdXREZXBlbmRlbmNpZXM6IGlucHV0cy5tYXAoKF9pbnB1dCwgX2luZGV4KSA9PiAndHlwZScpLFxuICAgIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzLFxuICAgICAgZGlzcGF0Y2hHcm91cDoge1xuICAgICAgICB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIGhpZGRlblNpemUpLFxuICAgICAgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBza2lwTGF5ZXJOb3JtID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBTa2lwTGF5ZXJOb3JtQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICAvLyBUT0RPOiBpbml0aWFsaXplIGlzVHJhaW5pbmcgZnJvbSBDb21wdXRlQ29udGV4dFxuICBjb25zdCBpc1RyYWluaW5nID0gZmFsc2U7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgLy8gTWVhbiBhbmQgSW52U3RkRGV2IGFyZSBvbmx5IHVzZWQgaW4gdHJhaW5pbmcgbW9kZSBhbmQgYXJlIG5vdCByZXF1aXJlZCBmb3IgaW5mZXJlbmNlLlxuICAvLyBUaGV5IGFyZSBhZGRlZCBoZXJlIGZvciBjb21wbGV0ZW5lc3Mgb25seS5cbiAgY29uc3Qgb3V0cHV0cyA9IFswXTtcbiAgaWYgKGNvbnRleHQub3V0cHV0Q291bnQgPiAxKSB7XG4gICAgb3V0cHV0cy5wdXNoKGlzVHJhaW5pbmcgPyAxIDogLTMpO1xuICB9XG4gIGlmIChjb250ZXh0Lm91dHB1dENvdW50ID4gMikge1xuICAgIG91dHB1dHMucHVzaChpc1RyYWluaW5nID8gMiA6IC0zKTtcbiAgfVxuICBpZiAoY29udGV4dC5vdXRwdXRDb3VudCA+IDMpIHtcbiAgICBvdXRwdXRzLnB1c2goMyk7XG4gIH1cbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZVNraXBMYXllck5vcm1Qcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgYXR0cmlidXRlcywgY29udGV4dC5vdXRwdXRDb3VudCwgaXNUcmFpbmluZyksIHtcbiAgICBvdXRwdXRzLFxuICB9KTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQsIFByb2dyYW1JbmZvLCBQcm9ncmFtVW5pZm9ybSwgVGVuc29ySW5mbyB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsXG4gIGdldEVsZW1lbnRBdCxcbiAgSW5kaWNlc0hlbHBlcixcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgVW5pZm9ybXNBcnJheVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBTbGljZUF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBzdGFydHM6IG51bWJlcltdO1xuICByZWFkb25seSBlbmRzOiBudW1iZXJbXTtcbiAgcmVhZG9ubHkgYXhlczogbnVtYmVyW107XG59XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBTbGljZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCA8IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3RvbyBmZXcgaW5wdXRzJyk7XG4gIH1cbiAgaWYgKGF0dHJpYnV0ZXMuYXhlcy5sZW5ndGggIT09IDApIHtcbiAgICBpZiAoYXR0cmlidXRlcy5heGVzLmxlbmd0aCAhPT0gYXR0cmlidXRlcy5zdGFydHMubGVuZ3RoIHx8IGF0dHJpYnV0ZXMuYXhlcy5sZW5ndGggIT09IGF0dHJpYnV0ZXMuZW5kcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignYXhlcywgc3RhcnRzIGFuZCBlbmRzIG11c3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGgnKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoYXR0cmlidXRlcy5zdGFydHMubGVuZ3RoICE9PSBhdHRyaWJ1dGVzLmVuZHMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzdGFydHMgYW5kIGVuZHMgbXVzdCBoYXZlIHRoZSBzYW1lIGxlbmd0aCcpO1xuICB9XG4gIGlucHV0cy5zbGljZSgxKS5mb3JFYWNoKChfLCBpZHgpID0+IHtcbiAgICBpZiAoaW5wdXRzW2lkeCArIDFdLmRhdGFUeXBlICE9PSBEYXRhVHlwZS5pbnQzMiAmJiBpbnB1dHNbaWR4ICsgMV0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmludDY0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYElucHV0ICR7aWR4fSBtdXN0IGJlIGFuIGFycmF5IG9mIGludDMyIG9yIGludDY0YCk7XG4gICAgfVxuICB9KTtcbn07XG5cbmNvbnN0IHJlYWRJbnB1dCA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgaWR4OiBudW1iZXIpOiBudW1iZXJbXSA9PiB7XG4gIGNvbnN0IGlucHV0OiBudW1iZXJbXSA9IFtdO1xuICBpZiAoaW5wdXRzLmxlbmd0aCA+IGlkeCkge1xuICAgIGlmIChpbnB1dHNbaWR4XS5kYXRhVHlwZSA9PT0gRGF0YVR5cGUuaW50NjQpIHtcbiAgICAgIGlucHV0c1tpZHhdLmdldEJpZ0ludDY0QXJyYXkoKS5mb3JFYWNoKCh2KSA9PiBpbnB1dC5wdXNoKE51bWJlcih2KSkpO1xuICAgIH0gZWxzZSBpZiAoaW5wdXRzW2lkeF0uZGF0YVR5cGUgPT09IERhdGFUeXBlLmludDMyKSB7XG4gICAgICBpbnB1dHNbaWR4XS5nZXRJbnQzMkFycmF5KCkuZm9yRWFjaCgodikgPT4gaW5wdXQucHVzaChOdW1iZXIodikpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnB1dCAke2lkeH0gbXVzdCBiZSBhbiBhcnJheSBvZiBpbnQzMiBvciBpbnQ2NGApO1xuICAgIH1cbiAgfVxuICByZXR1cm4gaW5wdXQ7XG59O1xuXG5jb25zdCBjcmVhdGVTbGljZUF0dHJpYnV0ZXNGcm9tSW5wdXRzID0gKFxuICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSxcbiAgYXR0cmlidXRlczogU2xpY2VBdHRyaWJ1dGVzLFxuKTogU2xpY2VBdHRyaWJ1dGVzID0+IHtcbiAgaWYgKGlucHV0cy5sZW5ndGggPiAxKSB7XG4gICAgY29uc3Qgc3RhcnRzOiBudW1iZXJbXSA9IHJlYWRJbnB1dChpbnB1dHMsIDEpO1xuICAgIGNvbnN0IGVuZHM6IG51bWJlcltdID0gcmVhZElucHV0KGlucHV0cywgMik7XG4gICAgbGV0IGF4ZXM6IG51bWJlcltdID0gcmVhZElucHV0KGlucHV0cywgMyk7XG4gICAgaWYgKGF4ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBheGVzID0gWy4uLkFycmF5KGlucHV0c1swXS5kaW1zLmxlbmd0aCkua2V5cygpXTtcbiAgICB9XG4gICAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IHN0YXJ0cywgZW5kcywgYXhlcyB9KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYXR0cmlidXRlcztcbiAgfVxufTtcblxuY29uc3QgZml4U3RhcnRFbmRWYWx1ZXMgPSAoXG4gIHZhbHVlOiBudW1iZXIsXG4gIGluZGV4OiBudW1iZXIsXG4gIGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICBheGVzOiByZWFkb25seSBudW1iZXJbXSxcbiAgc3RlcHM6IHJlYWRvbmx5IG51bWJlcltdLFxuKTogbnVtYmVyID0+IHtcbiAgbGV0IG5ld1ZhbHVlID0gdmFsdWU7XG4gIGlmICh2YWx1ZSA8IDApIHtcbiAgICBuZXdWYWx1ZSArPSBpbnB1dFNoYXBlW2F4ZXNbaW5kZXhdXTtcbiAgfVxuICBpZiAoc3RlcHNbaW5kZXhdIDwgMCkge1xuICAgIHJldHVybiBNYXRoLm1heCgwLCBNYXRoLm1pbihuZXdWYWx1ZSwgaW5wdXRTaGFwZVtheGVzW2luZGV4XV0gLSAxKSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIE1hdGgubWF4KDAsIE1hdGgubWluKG5ld1ZhbHVlLCBpbnB1dFNoYXBlW2F4ZXNbaW5kZXhdXSkpO1xuICB9XG59O1xuXG5jb25zdCBjYWxjdWxhdGVJbnB1dEluZGljZXNJbXBsID0gKFxuICBpbnB1dDogSW5kaWNlc0hlbHBlcixcbiAgb3V0cHV0OiBJbmRpY2VzSGVscGVyLFxuICBpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbik6IHN0cmluZyA9PlxuICBgZm4gY2FsY3VsYXRlSW5wdXRJbmRpY2VzKG91dHB1dF9pbmRpY2VzOiAke291dHB1dC50eXBlLmluZGljZXN9KSAtPiAke2lucHV0LnR5cGUuaW5kaWNlc30ge1xuICAgICAgICAgIHZhciBpbnB1dF9pbmRpY2VzOiAke2lucHV0LnR5cGUuaW5kaWNlc307XG4gICAgICAgICAgdmFyIGNhcnJ5ID0gMHU7XG4gICAgICAgICAgZm9yICh2YXIgaSA9ICR7aW5wdXRTaGFwZS5sZW5ndGh9OyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgbGV0IGlucHV0X3NoYXBlX2kgPSAke2dldEVsZW1lbnRBdCgndW5pZm9ybXMuaW5wdXRfc2hhcGUnLCAnaScsIGlucHV0U2hhcGUubGVuZ3RoKX07XG4gICAgICAgICAgICBsZXQgc3RlcHNfaSA9ICR7Z2V0RWxlbWVudEF0KCd1bmlmb3Jtcy5zdGVwcycsICdpJywgaW5wdXRTaGFwZS5sZW5ndGgpfTtcbiAgICAgICAgICAgIGxldCBzaWduc19pID0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnNpZ25zJywgJ2knLCBpbnB1dFNoYXBlLmxlbmd0aCl9O1xuICAgICAgICAgICAgbGV0IHN0YXJ0c19pID0gJHtnZXRFbGVtZW50QXQoJ3VuaWZvcm1zLnN0YXJ0cycsICdpJywgaW5wdXRTaGFwZS5sZW5ndGgpfTtcbiAgICAgICAgICAgIHZhciBvdXRwdXRfaW5kZXggPSAke291dHB1dC5pbmRpY2VzR2V0KCdvdXRwdXRfaW5kaWNlcycsICdpJyl9O1xuICAgICAgICAgICAgdmFyIGlucHV0X2luZGV4ID0gb3V0cHV0X2luZGV4ICogc3RlcHNfaSArIHN0YXJ0c19pICsgY2Fycnk7XG4gICAgICAgICAgICBjYXJyeSA9IGlucHV0X2luZGV4IC8gaW5wdXRfc2hhcGVfaTtcbiAgICAgICAgICAgIGlucHV0X2luZGV4ID0gaW5wdXRfaW5kZXggJSBpbnB1dF9zaGFwZV9pO1xuICAgICAgICAgICAgaWYgKHNpZ25zX2kgPCAwKSB7XG4gICAgICAgICAgICAgIGlucHV0X2luZGV4ID0gaW5wdXRfc2hhcGVfaSAtIGlucHV0X2luZGV4IC0gMXUgKyBzdGFydHNfaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR7aW5wdXQuaW5kaWNlc1NldCgnaW5wdXRfaW5kaWNlcycsICdpJywgJ2lucHV0X2luZGV4Jyl9O1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gaW5wdXRfaW5kaWNlcztcbiAgICAgIH1gO1xuXG5jb25zdCBjcmVhdGVTbGljZVByb2dyYW1JbmZvID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBTbGljZUF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgaW5wdXRTaXplID0gU2hhcGVVdGlsLnNpemUoaW5wdXRTaGFwZSk7XG4gIGNvbnN0IGF4ZXMgPVxuICAgIGF0dHJpYnV0ZXMuYXhlcy5sZW5ndGggPiAwXG4gICAgICA/IFNoYXBlVXRpbC5ub3JtYWxpemVBeGVzKGF0dHJpYnV0ZXMuYXhlcywgaW5wdXRTaGFwZS5sZW5ndGgpXG4gICAgICA6IFsuLi5BcnJheShpbnB1dFNoYXBlLmxlbmd0aCkua2V5cygpXTtcbiAgbGV0IHN0ZXBzID0gcmVhZElucHV0KGlucHV0cywgNCk7XG4gIHN0ZXBzLmZvckVhY2goXG4gICAgKHN0ZXApID0+XG4gICAgICBzdGVwICE9PSAwIHx8XG4gICAgICAoKCkgPT4ge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3N0ZXAgY2Fubm90IGJlIDAnKTtcbiAgICAgIH0pLFxuICApO1xuICBpZiAoc3RlcHMubGVuZ3RoID09PSAwKSB7XG4gICAgc3RlcHMgPSBBcnJheShheGVzLmxlbmd0aCkuZmlsbCgxKTtcbiAgfVxuICBjb25zdCBzdGFydHMgPSBhdHRyaWJ1dGVzLnN0YXJ0cy5tYXAoKHN0YXJ0LCBpKSA9PiBmaXhTdGFydEVuZFZhbHVlcyhzdGFydCwgaSwgaW5wdXRTaGFwZSwgYXhlcywgc3RlcHMpKTtcblxuICBjb25zdCBlbmRzID0gYXR0cmlidXRlcy5lbmRzLm1hcCgoZW5kLCBpKSA9PiBmaXhTdGFydEVuZFZhbHVlcyhlbmQsIGksIGlucHV0U2hhcGUsIGF4ZXMsIHN0ZXBzKSk7XG5cbiAgaWYgKGF4ZXMubGVuZ3RoICE9PSBzdGFydHMubGVuZ3RoIHx8IGF4ZXMubGVuZ3RoICE9PSBlbmRzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignc3RhcnQsIGVuZHMgYW5kIGF4ZXMgc2hvdWxkIGhhdmUgdGhlIHNhbWUgbnVtYmVyIG9mIGVsZW1lbnRzJyk7XG4gIH1cblxuICBpZiAoYXhlcy5sZW5ndGggIT09IGlucHV0U2hhcGUubGVuZ3RoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dFNoYXBlLmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAoIWF4ZXMuaW5jbHVkZXMoaSkpIHtcbiAgICAgICAgc3RhcnRzLnNwbGljZShpLCAwLCAwKTtcbiAgICAgICAgZW5kcy5zcGxpY2UoaSwgMCwgaW5wdXRTaGFwZVtpXSk7XG4gICAgICAgIHN0ZXBzLnNwbGljZShpLCAwLCAxKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgY29uc3Qgc2lnbnMgPSBzdGVwcy5tYXAoKHN0ZXApID0+IE1hdGguc2lnbihzdGVwKSk7XG4gIC8vIENvbnZlcnQgbmVnYXRpdmUgc3RlcHMgdG8gcG9zaXRpdmUgc3RlcHMgYW5kIHJldmVyc2Ugc3RhcnRzIGFuZCBlbmRzXG4gIHN0ZXBzLmZvckVhY2goKHN0ZXAsIGksIGFycmF5KSA9PiB7XG4gICAgaWYgKHN0ZXAgPCAwKSB7XG4gICAgICBjb25zdCBudW1TdGVwcyA9IChlbmRzW2ldIC0gc3RhcnRzW2ldKSAvIHN0ZXA7XG4gICAgICBjb25zdCBuZXdFbmQgPSBzdGFydHNbaV07XG4gICAgICBjb25zdCBuZXdTdGFydCA9IG5ld0VuZCArIG51bVN0ZXBzICogc3RlcHNbaV07XG4gICAgICBzdGFydHNbaV0gPSBuZXdTdGFydDtcbiAgICAgIGVuZHNbaV0gPSBuZXdFbmQ7XG4gICAgICBhcnJheVtpXSA9IC1zdGVwO1xuICAgIH1cbiAgfSk7XG4gIC8vIE91dHB1dCByYW5rIGlzIGV4cGVjdGVkIHRvIGJlIGxlc3MgdGhhbiBvciBlcXVhbCB0byB0aGUgaW5wdXQgcmFuay5cbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dFNoYXBlLnNsaWNlKDApO1xuICBheGVzLmZvckVhY2goKGF4aXMsIF8pID0+IHtcbiAgICBvdXRwdXRTaGFwZVtheGlzXSA9IE1hdGguY2VpbCgoZW5kc1theGlzXSAtIHN0YXJ0c1theGlzXSkgLyBzdGVwc1theGlzXSk7XG4gIH0pO1xuICBjb25zdCBvdXRwdXRUZW5zb3JJbmZvOiBUZW5zb3JJbmZvID0geyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSB9O1xuXG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCk7XG4gIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBpbnB1dHNbMF0uZGF0YVR5cGUsIGlucHV0c1swXS5kaW1zLmxlbmd0aCk7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gIGNvbnN0IHVuaWZvcm1zOiBVbmlmb3Jtc0FycmF5VHlwZSA9IFtcbiAgICB7IG5hbWU6ICdvdXRwdXRTaXplJywgdHlwZTogJ3UzMicgfSxcbiAgICB7IG5hbWU6ICdzdGFydHMnLCB0eXBlOiAndTMyJywgbGVuZ3RoOiBzdGFydHMubGVuZ3RoIH0sXG4gICAgeyBuYW1lOiAnc2lnbnMnLCB0eXBlOiAnaTMyJywgbGVuZ3RoOiBzaWducy5sZW5ndGggfSxcbiAgICB7IG5hbWU6ICdzdGVwcycsIHR5cGU6ICd1MzInLCBsZW5ndGg6IHN0ZXBzLmxlbmd0aCB9LFxuICBdO1xuXG4gIGNvbnN0IHByb2dyYW1Vbmlmb3JtczogUHJvZ3JhbVVuaWZvcm1bXSA9IFtcbiAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogb3V0cHV0U2l6ZSB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBzdGFydHMgfSxcbiAgICB7IHR5cGU6IERhdGFUeXBlLmludDMyLCBkYXRhOiBzaWducyB9LFxuICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBzdGVwcyB9LFxuICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1swXS5kaW1zLCBvdXRwdXRTaGFwZSksXG4gIF07XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm1zKHVuaWZvcm1zKS5kZWNsYXJlVmFyaWFibGVzKGlucHV0LCBvdXRwdXQpfVxuICAgICAgICAke2NhbGN1bGF0ZUlucHV0SW5kaWNlc0ltcGwoaW5wdXQsIG91dHB1dCwgaW5wdXRTaGFwZSl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLm91dHB1dFNpemUnKX1cbiAgICAgICAgICBsZXQgb3V0cHV0X2luZGljZXMgPSAke291dHB1dC5vZmZzZXRUb0luZGljZXMoJ2dsb2JhbF9pZHgnKX07XG4gICAgICAgICAgbGV0IGlucHV0X2luZGljZXMgPSBjYWxjdWxhdGVJbnB1dEluZGljZXMob3V0cHV0X2luZGljZXMpO1xuICAgICAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgaW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJykpfVxuICAgICAgfWA7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ1NsaWNlJyxcbiAgICBzaGFkZXJDYWNoZTogeyBoaW50OiBgJHtzaWducy5sZW5ndGh9XyR7c3RhcnRzLmxlbmd0aH1fJHtzdGVwcy5sZW5ndGh9YCwgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuayddIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbb3V0cHV0VGVuc29ySW5mb10sXG4gICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IE1hdGguY2VpbChpbnB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtcyxcbiAgICB9KSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBzbGljZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogU2xpY2VBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgY29uc3QgdXBkYXRlZEF0dHJpYnV0ZXMgPSBjcmVhdGVTbGljZUF0dHJpYnV0ZXNGcm9tSW5wdXRzKGNvbnRleHQuaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZVNsaWNlUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIHVwZGF0ZWRBdHRyaWJ1dGVzKSwgeyBpbnB1dHM6IFswXSB9KTtcbiAgLy8gaWYgKFNoYXBlVXRpbC5zaXplKHByb2dyYW0ub3V0cHV0c1swXS5kaW1zKSA+IDApIHtcbiAgLy8gICBjb250ZXh0LmNvbXB1dGUocHJvZ3JhbUluZm9Mb2FkZXIsIHtpbnB1dHM6IFswXX0pO1xuICAvLyB9IGVsc2Uge1xuICAvLyAgIC8vIFRPRE86IHN1cHBvcnQgZW1wdHkgb3V0cHV0XG4gIC8vICAgdGhyb3cgbmV3IEVycm9yKCdzbGljZTogb3V0cHV0IHNpemUgaXMgMCcpO1xuICAvLyB9XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VTbGljZUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBTbGljZUF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBzdGFydHMgPSBhdHRyaWJ1dGVzLnN0YXJ0cyBhcyBudW1iZXJbXTtcbiAgY29uc3QgZW5kcyA9IGF0dHJpYnV0ZXMuZW5kcyBhcyBudW1iZXJbXTtcbiAgY29uc3QgYXhlcyA9IGF0dHJpYnV0ZXMuYXhlcyBhcyBudW1iZXJbXTtcbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7IHN0YXJ0cywgZW5kcywgYXhlcyB9KTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbi8vIFRPRE86IHRoaXMgaXMgdGhlIHNhbWUgbmFpdmUgaW1wbGVtZW50YXRpb24gd2UgdXNlIGZvciByZWR1Y2UgdGhhdCBoYXNcbi8vIHBlcmZvcm1hbmNlIGxpbWl0YXRpb25zIHdoZW4gdGhlIHJlZHVjZWQgYXhpcyBpcyBsb25nLiBOZWVkIHRvIGFkZFxuLy8gYSBvcHRpbWl6ZWQgY29kZXBhdGggZm9yIHRoaXMuXG5cbmltcG9ydCB7IERhdGFUeXBlIH0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHsgVGVuc29yVmlldyB9IGZyb20gJy4uLy4uL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgQXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgfSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHsgQ29tcHV0ZUNvbnRleHQgfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQgeyBjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyB9IGZyb20gJy4vdHJhbnNwb3NlJztcblxuaW1wb3J0IHtcbiAgZ2V0TWF4Q29tcG9uZW50cyxcbiAgaW5wdXRWYXJpYWJsZSxcbiAgb3V0cHV0VmFyaWFibGUsXG4gIFNoYWRlckhlbHBlcixcbiAgc3VtVmVjdG9yLFxuICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUsXG59IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignU29mdG1heCBvcCByZXF1aXJlcyAxIGlucHV0LicpO1xuICB9XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIFNvZnRtYXhBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYXhpczogbnVtYmVyO1xufVxuXG5jb25zdCBjcmVhdGVTb2Z0bWF4UHJvZ3JhbUluZm8gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IFNvZnRtYXhBdHRyaWJ1dGVzKSA9PiB7XG4gIGNvbnN0IGlucHV0ID0gY29udGV4dC5pbnB1dHNbMF07XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dC5kaW1zO1xuICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUoaW5wdXRTaGFwZSk7XG4gIGNvbnN0IGlucHV0UmFuayA9IGlucHV0U2hhcGUubGVuZ3RoO1xuICBjb25zdCBheGlzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4aXMoYXR0cmlidXRlcy5heGlzLCBpbnB1dFJhbmspO1xuICBjb25zdCBpc1RyYW5zcG9zZVJlcXVpcmVkID0gYXhpcyA8IGlucHV0U2hhcGUubGVuZ3RoIC0gMTtcbiAgbGV0IHRyYW5zcG9zZWRJbnB1dDogVGVuc29yVmlldztcbiAgbGV0IHBlcm06IG51bWJlcltdID0gW107XG5cbiAgaWYgKGlzVHJhbnNwb3NlUmVxdWlyZWQpIHtcbiAgICBwZXJtID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogaW5wdXRSYW5rIH0sIChfLCBpKSA9PiBpKTtcbiAgICBwZXJtW2F4aXNdID0gaW5wdXRSYW5rIC0gMTtcbiAgICBwZXJtW2lucHV0UmFuayAtIDFdID0gYXhpcztcblxuICAgIHRyYW5zcG9zZWRJbnB1dCA9IGNvbnRleHQuY29tcHV0ZShjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhpbnB1dCwgcGVybSksIHtcbiAgICAgIGlucHV0czogW2lucHV0XSxcbiAgICAgIG91dHB1dHM6IFstMV0sXG4gICAgfSlbMF07XG4gIH0gZWxzZSB7XG4gICAgdHJhbnNwb3NlZElucHV0ID0gaW5wdXQ7XG4gIH1cblxuICBjb25zdCB0cmFuc3Bvc2VkSW5wdXRTaGFwZSA9IHRyYW5zcG9zZWRJbnB1dC5kaW1zO1xuICBjb25zdCBjb2xzID0gdHJhbnNwb3NlZElucHV0U2hhcGVbaW5wdXRSYW5rIC0gMV07XG4gIGNvbnN0IHJvd3MgPSBvdXRwdXRTaXplIC8gY29scztcbiAgY29uc3QgY29tcG9uZW50cyA9IGdldE1heENvbXBvbmVudHMoY29scyk7XG4gIGNvbnN0IHBhY2tlZENvbHMgPSBjb2xzIC8gY29tcG9uZW50cztcbiAgbGV0IFdHID0gNjQ7XG4gIC8vIElmIG9ubHkgb25lIHdvcmtncm91cCBpcyBkaXNwYXRjaGVkLCBpbmNyZWFzZSB3b3JrZ3JvdXBTaXplIHRvIGltcHJvdmUgcGFyYWxsZWxpc20uXG4gIGlmIChyb3dzID09PSAxKSB7XG4gICAgV0cgPSAyNTY7XG4gIH1cbiAgY29uc3QgbWF4VmVjdG9yID0gKG5hbWU6IHN0cmluZywgY29tcG9uZW50czogbnVtYmVyKSA9PiB7XG4gICAgaWYgKGNvbXBvbmVudHMgPT09IDQpIHtcbiAgICAgIHJldHVybiBgbWF4KG1heCgke25hbWV9LngsICR7bmFtZX0ueSksIG1heCgke25hbWV9LnosICR7bmFtZX0udykpYDtcbiAgICB9IGVsc2UgaWYgKGNvbXBvbmVudHMgPT09IDIpIHtcbiAgICAgIHJldHVybiBgbWF4KCR7bmFtZX0ueCwgJHtuYW1lfS55KWA7XG4gICAgfSBlbHNlIGlmIChjb21wb25lbnRzID09PSAzKSB7XG4gICAgICByZXR1cm4gYG1heChtYXgoJHtuYW1lfS54LCAke25hbWV9LnkpLCAke25hbWV9LnopYDtcbiAgICB9XG5cbiAgICByZXR1cm4gbmFtZTtcbiAgfTtcbiAgY29uc3QgeCA9IGlucHV0VmFyaWFibGUoJ3gnLCB0cmFuc3Bvc2VkSW5wdXQuZGF0YVR5cGUsIHRyYW5zcG9zZWRJbnB1dC5kaW1zLCBjb21wb25lbnRzKTtcbiAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0VmFyaWFibGUoJ3Jlc3VsdCcsIHRyYW5zcG9zZWRJbnB1dC5kYXRhVHlwZSwgdHJhbnNwb3NlZElucHV0LmRpbXMsIGNvbXBvbmVudHMpO1xuICBjb25zdCB2YWx1ZVR5cGUgPSB4LnR5cGUudmFsdWU7XG4gIC8vIDYuMi40IGluIHdnc2wgc3BlY1xuICBjb25zdCB0aHJlYWRNYXhEZWNsID1cbiAgICB0ZW5zb3JUeXBlVG9Xc2dsU3RvcmFnZVR5cGUodHJhbnNwb3NlZElucHV0LmRhdGFUeXBlKSA9PT0gJ2YzMidcbiAgICAgID8gYHZhciB0aHJlYWRNYXggPSAke3ZhbHVlVHlwZX0oLTMuNDAyODIzZSszOGYpO2BcbiAgICAgIDogYHZhciB0aHJlYWRNYXggPSAke3ZhbHVlVHlwZX0oLTY1NTA0LjBoKTtgO1xuICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcbiAgICAgIHZhcjx3b3JrZ3JvdXA+IHJvd01heFNoYXJlZCA6ICR7dmFsdWVUeXBlfTtcbiAgICAgIHZhcjx3b3JrZ3JvdXA+IHJvd1N1bVNoYXJlZCA6ICR7dmFsdWVUeXBlfTtcbiAgICAgIHZhcjx3b3JrZ3JvdXA+IHRocmVhZFNoYXJlZCA6IGFycmF5PCR7dmFsdWVUeXBlfSwgJHtXR30+O1xuXG4gICAgICBmbiBnZXRWYWx1ZShyb3c6IGkzMiwgY29sOiBpMzIsIHJvd19zdHJpZGU6IGkzMikgLT4gJHt2YWx1ZVR5cGV9IHtcbiAgICAgICAgbGV0IGluZGV4ID0gcm93ICogcm93X3N0cmlkZSArIGNvbDtcbiAgICAgICAgcmV0dXJuIHhbaW5kZXhdO1xuICAgICAgfVxuXG4gICAgICBmbiBzZXRWYWx1ZShyb3c6IGkzMiwgY29sOiBpMzIsIHJvd19zdHJpZGU6IGkzMiwgdmFsdWU6ICR7dmFsdWVUeXBlfSkge1xuICAgICAgICBsZXQgaW5kZXggPSByb3cgKiByb3dfc3RyaWRlICsgY29sO1xuICAgICAgICByZXN1bHRbaW5kZXhdID0gdmFsdWU7XG4gICAgICB9XG4gICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ3BhY2tlZENvbHMnLCAnaTMyJykuZGVjbGFyZVZhcmlhYmxlcyh4LCBvdXRwdXQpfVxuICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KFdHKX1cbiAgICAgICAgbGV0IGdpbmRleCA9IGkzMihnbG9iYWxfaWR4KTtcbiAgICAgICAgbGV0IGxpbmRleCA9IGkzMihsb2NhbF9pZHgpO1xuICAgICAgICBjb25zdCB3ZyA9ICR7V0d9O1xuICAgICAgICBsZXQgcm93ID0gZ2luZGV4IC8gd2c7XG4gICAgICAgIGxldCBjb2xzID0gdW5pZm9ybXMucGFja2VkQ29scztcbiAgICAgICAgbGV0IHJvd19zdHJpZGUgOiBpMzIgPSB1bmlmb3Jtcy5wYWNrZWRDb2xzO1xuXG4gICAgICAgIC8vIGZpbmQgdGhlIHJvd3MgbWF4XG4gICAgICAgICR7dGhyZWFkTWF4RGVjbH1cbiAgICAgICAgZm9yICh2YXIgY29sID0gbGluZGV4OyBjb2wgPCBjb2xzOyBjb2wgKz0gd2cpIHtcbiAgICAgICAgICBsZXQgdmFsdWUgPSBnZXRWYWx1ZShyb3csIGNvbCwgcm93X3N0cmlkZSk7XG4gICAgICAgICAgdGhyZWFkTWF4ID0gbWF4KHRocmVhZE1heCwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsaW5kZXggPCBjb2xzKSB7XG4gICAgICAgICAgdGhyZWFkU2hhcmVkW2xpbmRleF0gPSB0aHJlYWRNYXg7XG4gICAgICAgIH1cbiAgICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuXG4gICAgICAgIHZhciByZWR1Y2VTaXplID0gbWluKGNvbHMsIHdnKTtcbiAgICAgICAgZm9yICh2YXIgY3VyclNpemUgPSByZWR1Y2VTaXplID4+IDE7ICBjdXJyU2l6ZSA+IDA7IGN1cnJTaXplID0gcmVkdWNlU2l6ZSA+PiAxKSB7XG4gICAgICAgICAgcmVkdWNlU2l6ZSA9IGN1cnJTaXplICsgKHJlZHVjZVNpemUgJiAxKTtcbiAgICAgICAgICBpZiAobGluZGV4IDwgY3VyclNpemUpIHtcbiAgICAgICAgICAgIHRocmVhZFNoYXJlZFtsaW5kZXhdID0gbWF4KHRocmVhZFNoYXJlZFtsaW5kZXhdLCB0aHJlYWRTaGFyZWRbbGluZGV4ICsgcmVkdWNlU2l6ZV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxpbmRleCA9PSAwKSB7XG4gICAgICAgICAgcm93TWF4U2hhcmVkID0gJHt2YWx1ZVR5cGV9KCR7bWF4VmVjdG9yKCd0aHJlYWRTaGFyZWRbMF0nLCBjb21wb25lbnRzKX0pO1xuICAgICAgICB9XG4gICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgICAvLyBmaW5kIHRoZSByb3dzIHN1bVxuICAgICAgICB2YXIgdGhyZWFkU3VtID0gJHt2YWx1ZVR5cGV9KDAuMCk7XG4gICAgICAgIGZvciAodmFyIGNvbCA9IGxpbmRleDsgY29sIDwgY29sczsgY29sICs9IHdnKSB7XG4gICAgICAgICAgbGV0IHN1YkV4cCA9IGV4cChnZXRWYWx1ZShyb3csIGNvbCwgcm93X3N0cmlkZSkgLSByb3dNYXhTaGFyZWQpO1xuICAgICAgICAgIHRocmVhZFN1bSArPSBzdWJFeHA7XG4gICAgICAgIH1cbiAgICAgICAgdGhyZWFkU2hhcmVkW2xpbmRleF0gPSB0aHJlYWRTdW07XG4gICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcblxuICAgICAgICBmb3IgKHZhciBjdXJyU2l6ZSA9IHdnID4+IDE7ICBjdXJyU2l6ZSA+IDA7IGN1cnJTaXplID0gY3VyclNpemUgPj4gMSkge1xuICAgICAgICAgIGlmIChsaW5kZXggPCBjdXJyU2l6ZSkge1xuICAgICAgICAgICAgdGhyZWFkU2hhcmVkW2xpbmRleF0gPSB0aHJlYWRTaGFyZWRbbGluZGV4XSArIHRocmVhZFNoYXJlZFtsaW5kZXggKyBjdXJyU2l6ZV07XG4gICAgICAgICAgfVxuICAgICAgICAgIHdvcmtncm91cEJhcnJpZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobGluZGV4ID09IDApIHtcbiAgICAgICAgICByb3dTdW1TaGFyZWQgPSAke3ZhbHVlVHlwZX0oJHtzdW1WZWN0b3IoJ3RocmVhZFNoYXJlZFswXScsIGNvbXBvbmVudHMpfSk7XG4gICAgICAgIH1cbiAgICAgICAgd29ya2dyb3VwQmFycmllcigpO1xuXG4gICAgICAgIC8vIGNhbGN1bGF0ZSBmaW5hbCB2YWx1ZSBmb3IgZWFjaCBlbGVtZW50IGluIHRoZSByb3dcbiAgICAgICAgZm9yICh2YXIgY29sID0gbGluZGV4OyBjb2wgPCBjb2xzOyBjb2wgKz0gd2cpIHtcbiAgICAgICAgICBsZXQgdmFsdWUgPSBleHAoZ2V0VmFsdWUocm93LCBjb2wsIHJvd19zdHJpZGUpIC0gcm93TWF4U2hhcmVkKSAvIHJvd1N1bVNoYXJlZDtcbiAgICAgICAgICBzZXRWYWx1ZShyb3csIGNvbCwgcm93X3N0cmlkZSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9YDtcbiAgY29uc3QgcmVzdWx0ID0gY29udGV4dC5jb21wdXRlKFxuICAgIHtcbiAgICAgIG5hbWU6ICdTb2Z0bWF4JyxcbiAgICAgIC8vIE5vdGUgdGhhdCBpbiBKU0VQLCBXRyBzaXplIGlzIG5vdCBpbmNsdWRlZCBpbiBjYWNoZSBieSBkZWZhdWx0LCBidXQgV2ViR1BVIEVQIGl0IGlzLlxuICAgICAgc2hhZGVyQ2FjaGU6IHsgaGludDogYCR7Y29tcG9uZW50c307JHtXR31gLCBpbnB1dERlcGVuZGVuY2llczogWyd0eXBlJ10gfSxcbiAgICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICAgIG91dHB1dHM6IFt7IGRpbXM6IHRyYW5zcG9zZWRJbnB1dFNoYXBlLCBkYXRhVHlwZTogdHJhbnNwb3NlZElucHV0LmRhdGFUeXBlIH1dLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiB7IHg6IHJvd3MgfSxcbiAgICAgICAgcHJvZ3JhbVVuaWZvcm1zOiBbeyB0eXBlOiBEYXRhVHlwZS5pbnQzMiwgZGF0YTogcGFja2VkQ29scyB9XSxcbiAgICAgIH0pLFxuICAgICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIH0sXG4gICAge1xuICAgICAgaW5wdXRzOiBbdHJhbnNwb3NlZElucHV0XSxcbiAgICAgIG91dHB1dHM6IFtpc1RyYW5zcG9zZVJlcXVpcmVkID8gLTEgOiAwXSxcbiAgICB9LFxuICApWzBdO1xuXG4gIGlmIChpc1RyYW5zcG9zZVJlcXVpcmVkKSB7XG4gICAgY29udGV4dC5jb21wdXRlKGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvKHJlc3VsdCwgcGVybSksIHtcbiAgICAgIGlucHV0czogW3Jlc3VsdF0sXG4gICAgfSk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBzb2Z0bWF4ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBTb2Z0bWF4QXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNyZWF0ZVNvZnRtYXhQcm9ncmFtSW5mbyhjb250ZXh0LCBhdHRyaWJ1dGVzKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZVNvZnRtYXhBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogU29mdG1heEF0dHJpYnV0ZXMgPT5cbiAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHsgYXhpczogYXR0cmlidXRlcy5heGlzIGFzIG51bWJlciB9KTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRGF0YVR5cGUgfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBUZW5zb3JWaWV3IH0gZnJvbSAnLi4vLi4vdGVuc29yLXZpZXcnO1xuaW1wb3J0IHsgU2hhcGVVdGlsIH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCwgUHJvZ3JhbUluZm8gfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzLCBpbnB1dFZhcmlhYmxlLCBvdXRwdXRWYXJpYWJsZSwgU2hhZGVySGVscGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5jb25zdCBnZXRSZXBlYXRzID0gKHJlcGVhdHNUZW5zb3JWaWV3OiBUZW5zb3JWaWV3KTogcmVhZG9ubHkgbnVtYmVyW10gPT5cbiAgQXJyYXkuZnJvbShyZXBlYXRzVGVuc29yVmlldy5nZXRCaWdJbnQ2NEFycmF5KCksIE51bWJlcik7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RpbGUgcmVxdWlyZXMgMiBpbnB1dHMuJyk7XG4gIH1cblxuICBpZiAoXG4gICAgaW5wdXRzWzBdLmRhdGFUeXBlICE9PSBEYXRhVHlwZS5mbG9hdCAmJlxuICAgIGlucHV0c1swXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuZmxvYXQxNiAmJlxuICAgIGlucHV0c1swXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuaW50MzIgJiZcbiAgICBpbnB1dHNbMF0uZGF0YVR5cGUgIT09IERhdGFUeXBlLnVpbnQzMlxuICApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RpbGUgb25seSBzdXBwb3J0IGZsb2F0LCBmbG9hdDE2LCBpbnQzMiwgYW5kIHVpbnQzMiBkYXRhIHR5cGVzJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzFdLmRhdGFUeXBlICE9PSBEYXRhVHlwZS5pbnQ2NCkge1xuICAgIHRocm93IG5ldyBFcnJvcignVGlsZSBgcmVwZWF0c2AgaW5wdXQgc2hvdWxkIGJlIG9mIGludDY0IGRhdGEgdHlwZScpO1xuICB9XG5cbiAgaWYgKGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignVGlsZSBgcmVwZWF0c2AgaW5wdXQgc2hvdWxkIGJlIDEtRCcpO1xuICB9XG5cbiAgY29uc3QgcmVwZWF0czogcmVhZG9ubHkgbnVtYmVyW10gPSBnZXRSZXBlYXRzKGlucHV0c1sxXSk7XG5cbiAgaWYgKHJlcGVhdHMubGVuZ3RoICE9PSBpbnB1dHNbMF0uZGltcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RpbGUgYHJlcGVhdHNgIGlucHV0IHNob3VsZCBoYXZlIHNhbWUgbnVtYmVyIG9mIGVsZW1lbnRzIGFzIHJhbmsgb2YgaW5wdXQgZGF0YSB0ZW5zb3InKTtcbiAgfVxufTtcblxuY29uc3QgZ2V0T3V0cHV0U2hhcGUgPSAoaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHJlcGVhdHM6IHJlYWRvbmx5IG51bWJlcltdKTogcmVhZG9ubHkgbnVtYmVyW10gPT4ge1xuICBjb25zdCBvdXRwdXRTaGFwZTogbnVtYmVyW10gPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0U2hhcGUubGVuZ3RoOyArK2kpIHtcbiAgICBvdXRwdXRTaGFwZS5wdXNoKGlucHV0U2hhcGVbaV0gKiByZXBlYXRzW2ldKTtcbiAgfVxuXG4gIHJldHVybiBvdXRwdXRTaGFwZTtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVUaWxlUHJvZ3JhbUluZm8gPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIHNoYXBlPzogbnVtYmVyW10pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgcmVwZWF0czogcmVhZG9ubHkgbnVtYmVyW10gPSBzaGFwZSA9PSBudWxsID8gZ2V0UmVwZWF0cyhpbnB1dHNbMV0pIDogc2hhcGU7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gZ2V0T3V0cHV0U2hhcGUoaW5wdXRTaGFwZSwgcmVwZWF0cyk7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG5cbiAgY29uc3QgZGF0YVR5cGUgPSBpbnB1dHNbMF0uZGF0YVR5cGU7XG4gIGNvbnN0IGlucHV0ID0gaW5wdXRWYXJpYWJsZSgnaW5wdXQnLCBkYXRhVHlwZSwgaW5wdXRTaGFwZS5sZW5ndGgpO1xuICBjb25zdCBvdXRwdXQgPSBvdXRwdXRWYXJpYWJsZSgnb3V0cHV0JywgZGF0YVR5cGUsIG91dHB1dFNoYXBlLmxlbmd0aCk7XG5cbiAgY29uc3QgZ2V0U2hhZGVyU291cmNlID0gKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBgXG4gICAgICBjb25zdCBpbnB1dFNoYXBlID0gJHtpbnB1dC5pbmRpY2VzKC4uLmlucHV0U2hhcGUpfTtcbiAgICAgICR7c2hhZGVySGVscGVyLnJlZ2lzdGVyVW5pZm9ybSgnb3V0cHV0X3NpemUnLCAndTMyJykuZGVjbGFyZVZhcmlhYmxlcyhpbnB1dCwgb3V0cHV0KX1cbiAgICAgICR7c2hhZGVySGVscGVyLm1haW5TdGFydCgpfVxuICAgICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcygndW5pZm9ybXMub3V0cHV0X3NpemUnKX1cbiAgICAgIGxldCBvdXRwdXRfaW5kaWNlcyA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcygnZ2xvYmFsX2lkeCcpfTtcbiAgICAgIHZhciBpbnB1dF9pbmRpY2VzOiAke2lucHV0LnR5cGUuaW5kaWNlc307XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8ICR7aW5wdXRTaGFwZS5sZW5ndGh9OyBpKyspIHtcbiAgICAgICAgbGV0IGlucHV0X2RpbV9pID0gJHtpbnB1dC5pbmRpY2VzR2V0KCd1bmlmb3Jtcy5pbnB1dF9zaGFwZScsICdpJyl9O1xuICAgICAgICBsZXQgaW5wdXRfZGltX3ZhbHVlID0gJHtvdXRwdXQuaW5kaWNlc0dldCgnb3V0cHV0X2luZGljZXMnLCAnaScpfSAgJSBpbnB1dF9kaW1faTtcblxuICAgICAgICAke2lucHV0LmluZGljZXNTZXQoJ2lucHV0X2luZGljZXMnLCAnaScsICdpbnB1dF9kaW1fdmFsdWUnKX1cbiAgICAgIH1cbiAgICAgICR7b3V0cHV0LnNldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JywgaW5wdXQuZ2V0QnlJbmRpY2VzKCdpbnB1dF9pbmRpY2VzJykpfVxuICAgIH1gO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ1RpbGUnLFxuICAgIHNoYWRlckNhY2hlOiB7IGhpbnQ6IGAke3JlcGVhdHN9YCwgaW5wdXREZXBlbmRlbmNpZXM6IFsncmFuayddIH0sXG4gICAgZ2V0UnVuRGF0YTogKCkgPT4gKHtcbiAgICAgIG91dHB1dHM6IFt7IGRpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKSB9LFxuICAgICAgcHJvZ3JhbVVuaWZvcm1zOiBbXG4gICAgICAgIHsgdHlwZTogRGF0YVR5cGUudWludDMyLCBkYXRhOiBvdXRwdXRTaXplIH0sXG4gICAgICAgIC4uLmNyZWF0ZVRlbnNvclNoYXBlVmFyaWFibGVzKGlucHV0c1swXS5kaW1zLCBvdXRwdXRTaGFwZSksXG4gICAgICBdLFxuICAgIH0pLFxuICAgIGdldFNoYWRlclNvdXJjZSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCB0aWxlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZVRpbGVQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cyksIHsgaW5wdXRzOiBbMF0gfSk7XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBEYXRhVHlwZSB9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7IFRlbnNvclZpZXcgfSBmcm9tICcuLi8uLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBCcm9hZGNhc3RVdGlsLCBTaGFwZVV0aWwgfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7IENvbXB1dGVDb250ZXh0LCBQcm9ncmFtSW5mbyB9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHsgY3JlYXRlVGVuc29yU2hhcGVWYXJpYWJsZXMsIGlucHV0VmFyaWFibGUsIG91dHB1dFZhcmlhYmxlLCBTaGFkZXJIZWxwZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IGNyZWF0ZVdoZXJlT3BQcm9ncmFtU2hhZGVyID0gKFxuICBzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcixcbiAgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGRpbXNPdXRwdXQ6IHJlYWRvbmx5IG51bWJlcltdLFxuICBpc0Jyb2FkY2FzdDogYm9vbGVhbixcbiAgdHlwZU91dHB1dDogbnVtYmVyLFxuKSA9PiB7XG4gIGNvbnN0IG91dHB1dCA9IG91dHB1dFZhcmlhYmxlKCdvdXRwdXRfZGF0YScsIHR5cGVPdXRwdXQsIGRpbXNPdXRwdXQubGVuZ3RoLCA0KTtcbiAgY29uc3QgYSA9IGlucHV0VmFyaWFibGUoJ2FfZGF0YScsIGlucHV0c1sxXS5kYXRhVHlwZSwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoLCA0KTtcbiAgY29uc3QgYiA9IGlucHV0VmFyaWFibGUoJ2JfZGF0YScsIGlucHV0c1syXS5kYXRhVHlwZSwgaW5wdXRzWzJdLmRpbXMubGVuZ3RoLCA0KTtcbiAgY29uc3QgYyA9IGlucHV0VmFyaWFibGUoJ2NfZGF0YScsIGlucHV0c1swXS5kYXRhVHlwZSwgaW5wdXRzWzBdLmRpbXMubGVuZ3RoLCA0KTtcblxuICBsZXQgYXNzaWdubWVudDogc3RyaW5nO1xuICBjb25zdCBleHByZXNzaW9uID0gKGE6IHN0cmluZywgYjogc3RyaW5nLCBjOiBzdHJpbmcpID0+IGBzZWxlY3QoJHtifSwgJHthfSwgJHtjfSlgO1xuICBpZiAoIWlzQnJvYWRjYXN0KSB7XG4gICAgYXNzaWdubWVudCA9IG91dHB1dC5zZXRCeU9mZnNldChcbiAgICAgICdnbG9iYWxfaWR4JyxcbiAgICAgIGV4cHJlc3Npb24oYS5nZXRCeU9mZnNldCgnZ2xvYmFsX2lkeCcpLCBiLmdldEJ5T2Zmc2V0KCdnbG9iYWxfaWR4JyksIGMuZ2V0QnlPZmZzZXQoJ2dsb2JhbF9pZHgnKSksXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBzaW5nbGVBc3NpZ25tZW50ID0gKHJlc1N0cjogc3RyaW5nLCB4OiBudW1iZXIsIHR5cGVDYXN0ID0gJycpID0+IHtcbiAgICAgIGNvbnN0IGV4cHJlc3Npb25BID0gYGFfZGF0YVtpbmRleF9hJHt4fV1bY29tcG9uZW50X2Eke3h9XWA7XG4gICAgICBjb25zdCBleHByZXNzaW9uQiA9IGBiX2RhdGFbaW5kZXhfYiR7eH1dW2NvbXBvbmVudF9iJHt4fV1gO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICAgIGNvbnN0IGV4cHJlc3Npb25DID0gYGJvb2woY19kYXRhW2luZGV4X2Mke3h9XSAmICgweGZmdSA8PCAoY29tcG9uZW50X2Mke3h9ICogOCkpKWA7XG4gICAgICByZXR1cm4gYFxuICAgICAgICAgICAgbGV0IG91dHB1dF9pbmRpY2VzJHt4fSA9ICR7b3V0cHV0Lm9mZnNldFRvSW5kaWNlcyhgZ2xvYmFsX2lkeCAqIDR1ICsgJHt4fXVgKX07XG4gICAgICAgICAgICBsZXQgb2Zmc2V0X2Eke3h9ID0gJHthLmJyb2FkY2FzdGVkSW5kaWNlc1RvT2Zmc2V0KGBvdXRwdXRfaW5kaWNlcyR7eH1gLCBvdXRwdXQpfTtcbiAgICAgICAgICAgIGxldCBvZmZzZXRfYiR7eH0gPSAke2IuYnJvYWRjYXN0ZWRJbmRpY2VzVG9PZmZzZXQoYG91dHB1dF9pbmRpY2VzJHt4fWAsIG91dHB1dCl9O1xuICAgICAgICAgICAgbGV0IG9mZnNldF9jJHt4fSA9ICR7Yy5icm9hZGNhc3RlZEluZGljZXNUb09mZnNldChgb3V0cHV0X2luZGljZXMke3h9YCwgb3V0cHV0KX07XG4gICAgICAgICAgICBsZXQgaW5kZXhfYSR7eH0gPSBvZmZzZXRfYSR7eH0gLyA0dTtcbiAgICAgICAgICAgIGxldCBpbmRleF9iJHt4fSA9IG9mZnNldF9iJHt4fSAvIDR1O1xuICAgICAgICAgICAgbGV0IGluZGV4X2Mke3h9ID0gb2Zmc2V0X2Mke3h9IC8gNHU7XG4gICAgICAgICAgICBsZXQgY29tcG9uZW50X2Eke3h9ID0gb2Zmc2V0X2Eke3h9ICUgNHU7XG4gICAgICAgICAgICBsZXQgY29tcG9uZW50X2Ike3h9ID0gb2Zmc2V0X2Ike3h9ICUgNHU7XG4gICAgICAgICAgICBsZXQgY29tcG9uZW50X2Mke3h9ID0gb2Zmc2V0X2Mke3h9ICUgNHU7XG4gICAgICAgICAgICAke3Jlc1N0cn1bJHt4fV0gPSAke3R5cGVDYXN0fSgke2V4cHJlc3Npb24oZXhwcmVzc2lvbkEsIGV4cHJlc3Npb25CLCBleHByZXNzaW9uQyl9KTtcbiAgICAgICAgICBgO1xuICAgIH07XG4gICAgaWYgKHR5cGVPdXRwdXQgPT09IERhdGFUeXBlLmJvb2wpIHtcbiAgICAgIGFzc2lnbm1lbnQgPSBgXG4gICAgICAgICAgICB2YXIgZGF0YSA9IHZlYzQ8dTMyPigwKTtcbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDAsICd1MzInKX1cbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDEsICd1MzInKX1cbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDIsICd1MzInKX1cbiAgICAgICAgICAgICR7c2luZ2xlQXNzaWdubWVudCgnZGF0YScsIDMsICd1MzInKX1cbiAgICAgICAgICAgIG91dHB1dF9kYXRhW2dsb2JhbF9pZHhdID0gZG90KHZlYzQ8dTMyPigweDEsIDB4MTAwLCAweDEwMDAwLCAweDEwMDAwMDApLCB2ZWM0PHUzMj4oZGF0YSkpO2A7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFzc2lnbm1lbnQgPSBgXG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ291dHB1dF9kYXRhW2dsb2JhbF9pZHhdJywgMCl9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ291dHB1dF9kYXRhW2dsb2JhbF9pZHhdJywgMSl9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ291dHB1dF9kYXRhW2dsb2JhbF9pZHhdJywgMil9XG4gICAgICAgICAgICAke3NpbmdsZUFzc2lnbm1lbnQoJ291dHB1dF9kYXRhW2dsb2JhbF9pZHhdJywgMyl9XG4gICAgICAgICAgYDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYFxuICAgICAgICAke3NoYWRlckhlbHBlci5yZWdpc3RlclVuaWZvcm0oJ3ZlY19zaXplJywgJ3UzMicpLmRlY2xhcmVWYXJpYWJsZXMoYywgYSwgYiwgb3V0cHV0KX1cbiAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoJ3VuaWZvcm1zLnZlY19zaXplJyl9XG4gICAgICAgICR7YXNzaWdubWVudH1cbiAgICAgIH1gO1xufTtcblxuY29uc3QgY3JlYXRlV2hlcmVPcFByb2dyYW1JbmZvID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogUHJvZ3JhbUluZm8gPT4ge1xuICBjb25zdCBkaW1zQSA9IGlucHV0c1sxXS5kaW1zO1xuICBjb25zdCBkaW1zQiA9IGlucHV0c1syXS5kaW1zO1xuICBjb25zdCBkaW1zQyA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBvdXRwdXREYXRhVHlwZSA9IGlucHV0c1sxXS5kYXRhVHlwZTtcblxuICBjb25zdCBpc0Jyb2FkY2FzdCA9ICEoU2hhcGVVdGlsLmFyZUVxdWFsKGRpbXNBLCBkaW1zQikgJiYgU2hhcGVVdGlsLmFyZUVxdWFsKGRpbXNCLCBkaW1zQykpO1xuICBsZXQgb3V0cHV0U2hhcGUgPSBkaW1zQTtcbiAgbGV0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShkaW1zQSk7XG4gIC8vIFRPRE86IGRlYWwgd2l0aCB6ZXJvLXNpemVkIHRlbnNvcnMgKGVnLiBkaW1zPVsxLDBdKVxuXG4gIGlmIChpc0Jyb2FkY2FzdCkge1xuICAgIGNvbnN0IGNhbGN1bGF0ZWRTaGFwZSA9IEJyb2FkY2FzdFV0aWwuY2FsY1NoYXBlKEJyb2FkY2FzdFV0aWwuY2FsY1NoYXBlKGRpbXNBLCBkaW1zQiwgZmFsc2UpISwgZGltc0MsIGZhbHNlKTtcbiAgICBpZiAoIWNhbGN1bGF0ZWRTaGFwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgcGVyZm9ybSB3aGVyZSBvcCBvbiB0aGUgZ2l2ZW4gdGVuc29yc1wiKTtcbiAgICB9XG4gICAgb3V0cHV0U2hhcGUgPSBjYWxjdWxhdGVkU2hhcGU7XG4gICAgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgfVxuXG4gIGNvbnN0IHZlY1NpemUgPSBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDQpO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ1doZXJlJyxcbiAgICBzaGFkZXJDYWNoZTogeyBpbnB1dERlcGVuZGVuY2llczogWydyYW5rJywgJ3JhbmsnLCAncmFuayddIH0sXG4gICAgZ2V0U2hhZGVyU291cmNlOiAoc2hhZGVySGVscGVyKSA9PlxuICAgICAgY3JlYXRlV2hlcmVPcFByb2dyYW1TaGFkZXIoc2hhZGVySGVscGVyLCBpbnB1dHMsIG91dHB1dFNoYXBlLCBpc0Jyb2FkY2FzdCwgb3V0cHV0RGF0YVR5cGUpLFxuICAgIGdldFJ1bkRhdGE6ICgpID0+ICh7XG4gICAgICBvdXRwdXRzOiBbeyBkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IG91dHB1dERhdGFUeXBlIH1dLFxuICAgICAgZGlzcGF0Y2hHcm91cDogeyB4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovIC8gNCAvKiB2ZWMgc2l6ZSAqLykgfSxcbiAgICAgIHByb2dyYW1Vbmlmb3JtczogW1xuICAgICAgICB7IHR5cGU6IERhdGFUeXBlLnVpbnQzMiwgZGF0YTogdmVjU2l6ZSB9LFxuICAgICAgICAuLi5jcmVhdGVUZW5zb3JTaGFwZVZhcmlhYmxlcyhkaW1zQywgZGltc0EsIGRpbXNCLCBvdXRwdXRTaGFwZSksXG4gICAgICBdLFxuICAgIH0pLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHdoZXJlID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVXaGVyZU9wUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMpKTtcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IGFyZ01heCwgYXJnTWluLCBwYXJzZUFyZ01pbk1heEF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9hcmdtaW5tYXgnO1xuaW1wb3J0IHsgYXR0ZW50aW9uIH0gZnJvbSAnLi9vcHMvYXR0ZW50aW9uJztcbmltcG9ydCB7IGJhdGNoTm9ybSB9IGZyb20gJy4vb3BzL2JhdGNoLW5vcm0nO1xuaW1wb3J0IHsgYmlhc0FkZCB9IGZyb20gJy4vb3BzL2JpYXMtYWRkJztcbmltcG9ydCB7IGJpYXNTcGxpdEdlbHUgfSBmcm9tICcuL29wcy9iaWFzLXNwbGl0LWdlbHUnO1xuaW1wb3J0ICogYXMgYmluYXJ5T3BzIGZyb20gJy4vb3BzL2JpbmFyeS1vcCc7XG5pbXBvcnQgeyBjb25jYXQsIHBhcnNlQ29uY2F0QXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL2NvbmNhdCc7XG5pbXBvcnQgeyBjb252LCBwYXJzZUNvbnZBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvY29udic7XG5pbXBvcnQgeyBjb252VHJhbnNwb3NlLCBwYXJzZUNvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvY29udi10cmFuc3Bvc2UnO1xuaW1wb3J0IHsgY3Vtc3VtLCBwYXJzZUN1bVN1bUF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9jdW1zdW0nO1xuaW1wb3J0IHsgZGVwdGhUb1NwYWNlLCBwYXJzZURlcHRoVG9TcGFjZUF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9kZXB0aC10by1zcGFjZSc7XG5pbXBvcnQgeyBlaW5zdW0sIHBhcnNlRWluc3VtQXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL2VpbnN1bSc7XG5pbXBvcnQgeyBleHBhbmQgfSBmcm9tICcuL29wcy9leHBhbmQnO1xuaW1wb3J0IHsgZmFzdEdlbHUgfSBmcm9tICcuL29wcy9mYXN0LWdlbHUnO1xuaW1wb3J0IHsgZ2F0aGVyLCBwYXJzZUdhdGhlckF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9nYXRoZXInO1xuaW1wb3J0IHsgZ2F0aGVyTkQsIHBhcnNlR2F0aGVyTkRBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvZ2F0aGVyLW5kJztcbmltcG9ydCB7IGdhdGhlckJsb2NrUXVhbnRpemVkLCBwYXJzZUdhdGhlckJsb2NrUXVhbnRpemVkQXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL2dhdGhlci1ibG9jay1xdWFudGl6ZWQnO1xuaW1wb3J0IHsgZ2F0aGVyRWxlbWVudHMsIHBhcnNlR2F0aGVyRWxlbWVudHNBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvZ2F0aGVyLWVsZW1lbnRzJztcbmltcG9ydCB7IGdlbW0sIHBhcnNlR2VtbUF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9nZW1tJztcbmltcG9ydCB7IGdyaWRTYW1wbGUsIHBhcnNlR3JpZFNhbXBsZUF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9ncmlkLXNhbXBsZSc7XG5pbXBvcnQgeyBncm91cFF1ZXJ5QXR0ZW50aW9uIH0gZnJvbSAnLi9vcHMvZ3JvdXAtcXVlcnktYXR0ZW50aW9uJztcbmltcG9ydCB7IGluc3RhbmNlTm9ybSB9IGZyb20gJy4vb3BzL2luc3RhbmNlLW5vcm0nO1xuaW1wb3J0IHsgbGF5ZXJOb3JtIH0gZnJvbSAnLi9vcHMvbGF5ZXItbm9ybSc7XG5pbXBvcnQgeyBtYXRNdWwgfSBmcm9tICcuL29wcy9tYXRtdWwnO1xuaW1wb3J0IHsgbWF0TXVsTkJpdHMsIHBhcnNlTWF0TXVsTkJpdHNBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvbWF0bXVsbmJpdHMnO1xuaW1wb3J0IHsgbXVsdGlIZWFkQXR0ZW50aW9uLCBwYXJzZU11bHRpSGVhZEF0dGVudGlvbkF0dHJpYnV0ZXMgfSBmcm9tICcuL29wcy9tdWx0aWhlYWQtYXR0ZW50aW9uJztcbmltcG9ydCB7IHBhZCB9IGZyb20gJy4vb3BzL3BhZCc7XG5pbXBvcnQgKiBhcyBwb29sIGZyb20gJy4vb3BzL3Bvb2wnO1xuaW1wb3J0IHsgZGVxdWFudGl6ZUxpbmVhciwgcGFyc2VEZXF1YW50aXplTGluZWFyQXR0cmlidXRlcyB9IGZyb20gJy4vb3BzL3F1YW50aXplLWxpbmVhcic7XG5pbXBvcnQgeyByYW5nZSB9IGZyb20gJy4vb3BzL3JhbmdlJztcbmltcG9ydCB7IHNjYXR0ZXJORCwgcGFyc2VTY2F0dGVyTkRBdHRyaWJ1dGVzIH0gZnJvbSAnLi9vcHMvc2NhdHRlci1uZCc7XG5pbXBvcnQge1xuICByZWR1Y2VMMSxcbiAgcmVkdWNlTDIsXG4gIHJlZHVjZUxvZ1N1bSxcbiAgcmVkdWNlTG9nU3VtRXhwLFxuICByZWR1Y2VNYXgsXG4gIHJlZHVjZU1lYW4sXG4gIHJlZHVjZU1pbixcbiAgcmVkdWNlUHJvZCxcbiAgcmVkdWNlU3VtLFxuICByZWR1Y2VTdW1TcXVhcmUsXG59IGZyb20gJy4vb3BzL3JlZHVjZSc7XG5pbXBvcnQgeyBwYXJzZVJlc2l6ZUF0dHJpYnV0ZXMsIHJlc2l6ZSB9IGZyb20gJy4vb3BzL3Jlc2l6ZSc7XG5pbXBvcnQgeyByb3RhcnlFbWJlZGRpbmcgfSBmcm9tICcuL29wcy9yb3RhcnktZW1iZWRkaW5nJztcbmltcG9ydCB7IHNraXBMYXllck5vcm0gfSBmcm9tICcuL29wcy9za2lwLWxheWVyLW5vcm0nO1xuaW1wb3J0IHsgcGFyc2VTbGljZUF0dHJpYnV0ZXMsIHNsaWNlIH0gZnJvbSAnLi9vcHMvc2xpY2UnO1xuaW1wb3J0IHsgcGFyc2VTb2Z0bWF4QXR0cmlidXRlcywgc29mdG1heCB9IGZyb20gJy4vb3BzL3NvZnRtYXgnO1xuaW1wb3J0IHsgcGFyc2VTcGxpdEF0dHJpYnV0ZXMsIHNwbGl0IH0gZnJvbSAnLi9vcHMvc3BsaXQnO1xuaW1wb3J0IHsgdGlsZSB9IGZyb20gJy4vb3BzL3RpbGUnO1xuaW1wb3J0IHsgcGFyc2VUcmFuc3Bvc2VBdHRyaWJ1dGVzLCB0cmFuc3Bvc2UgfSBmcm9tICcuL29wcy90cmFuc3Bvc2UnO1xuaW1wb3J0ICogYXMgdW5hcnlPcHMgZnJvbSAnLi9vcHMvdW5hcnktb3AnO1xuaW1wb3J0IHsgd2hlcmUgfSBmcm9tICcuL29wcy93aGVyZSc7XG5pbXBvcnQgeyBDb21wdXRlQ29udGV4dCB9IGZyb20gJy4vdHlwZXMnO1xuXG5leHBvcnQgdHlwZSBSdW5GdW5jdGlvbiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlPzogdW5rbm93bikgPT4gdm9pZDtcbmV4cG9ydCB0eXBlIFBhcnNlQXR0cmlidXRlRnVuY3Rpb24gPSAoYXR0cmlidXRlUmF3OiB1bmtub3duKSA9PiB1bmtub3duO1xuZXhwb3J0IHR5cGUgT3BlcmF0b3JJbXBsZW1lbnRhdGlvbiA9IFtSdW5GdW5jdGlvbl0gfCBbUnVuRnVuY3Rpb24sIFBhcnNlQXR0cmlidXRlRnVuY3Rpb25dO1xuXG5leHBvcnQgY29uc3QgV0VCR1BVX09QX1JFU09MVkVfUlVMRVM6IE1hcDxzdHJpbmcsIE9wZXJhdG9ySW1wbGVtZW50YXRpb24+ID0gbmV3IE1hcChbXG4gIFsnQWJzJywgW3VuYXJ5T3BzLmFic11dLFxuICBbJ0Fjb3MnLCBbdW5hcnlPcHMuYWNvc11dLFxuICBbJ0Fjb3NoJywgW3VuYXJ5T3BzLmFjb3NoXV0sXG4gIFsnQWRkJywgW2JpbmFyeU9wcy5hZGRdXSxcbiAgWydBcmdNYXgnLCBbYXJnTWF4LCBwYXJzZUFyZ01pbk1heEF0dHJpYnV0ZXNdXSxcbiAgWydBcmdNaW4nLCBbYXJnTWluLCBwYXJzZUFyZ01pbk1heEF0dHJpYnV0ZXNdXSxcbiAgWydBc2luJywgW3VuYXJ5T3BzLmFzaW5dXSxcbiAgWydBc2luaCcsIFt1bmFyeU9wcy5hc2luaF1dLFxuICBbJ0F0YW4nLCBbdW5hcnlPcHMuYXRhbl1dLFxuICBbJ0F0YW5oJywgW3VuYXJ5T3BzLmF0YW5oXV0sXG4gIFsnQXR0ZW50aW9uJywgW2F0dGVudGlvbl1dLFxuICAvLyBUT0RPOiBzdXBwb3J0IG5ldyBhdHRyaWJ1dGVzIGZvciBBdmVyYWdlUG9vbC0xMFxuICBbJ0F2ZXJhZ2VQb29sJywgW3Bvb2wuYXZlcmFnZVBvb2wsIHBvb2wucGFyc2VBdmVyYWdlUG9vbEF0dHJpYnV0ZXNdXSxcbiAgWydCYXRjaE5vcm1hbGl6YXRpb24nLCBbYmF0Y2hOb3JtXV0sXG4gIFsnQmlhc0FkZCcsIFtiaWFzQWRkXV0sXG4gIFsnQmlhc1NwbGl0R2VsdScsIFtiaWFzU3BsaXRHZWx1XV0sXG4gIFsnQ2FzdCcsIFt1bmFyeU9wcy5jYXN0LCB1bmFyeU9wcy5wYXJzZUNhc3RBdHRyaWJ1dGVzXV0sXG4gIFsnQ2VpbCcsIFt1bmFyeU9wcy5jZWlsXV0sXG4gIFsnQ2xpcCcsIFt1bmFyeU9wcy5jbGlwXV0sXG4gIFsnQ29uY2F0JywgW2NvbmNhdCwgcGFyc2VDb25jYXRBdHRyaWJ1dGVzXV0sXG4gIFsnQ29udicsIFtjb252LCBwYXJzZUNvbnZBdHRyaWJ1dGVzXV0sXG4gIFsnQ29udlRyYW5zcG9zZScsIFtjb252VHJhbnNwb3NlLCBwYXJzZUNvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzXV0sXG4gIFsnQ29zJywgW3VuYXJ5T3BzLmNvc11dLFxuICBbJ0Nvc2gnLCBbdW5hcnlPcHMuY29zaF1dLFxuICBbJ0N1bVN1bScsIFtjdW1zdW0sIHBhcnNlQ3VtU3VtQXR0cmlidXRlc11dLFxuICBbJ0RlcHRoVG9TcGFjZScsIFtkZXB0aFRvU3BhY2UsIHBhcnNlRGVwdGhUb1NwYWNlQXR0cmlidXRlc11dLFxuICBbJ0RlcXVhbnRpemVMaW5lYXInLCBbZGVxdWFudGl6ZUxpbmVhciwgcGFyc2VEZXF1YW50aXplTGluZWFyQXR0cmlidXRlc11dLFxuICBbJ0RpdicsIFtiaW5hcnlPcHMuZGl2XV0sXG4gIFsnRWluc3VtJywgW2VpbnN1bSwgcGFyc2VFaW5zdW1BdHRyaWJ1dGVzXV0sXG4gIFsnRWx1JywgW3VuYXJ5T3BzLmVsdSwgdW5hcnlPcHMucGFyc2VBbHBoYUF0dHJpYnV0ZXNdXSxcbiAgWydFcXVhbCcsIFtiaW5hcnlPcHMuZXF1YWxdXSxcbiAgWydFcmYnLCBbdW5hcnlPcHMuZXJmXV0sXG4gIFsnRXhwJywgW3VuYXJ5T3BzLmV4cF1dLFxuICBbJ0V4cGFuZCcsIFtleHBhbmRdXSxcbiAgWydGYXN0R2VsdScsIFtmYXN0R2VsdV1dLFxuICBbJ0Zsb29yJywgW3VuYXJ5T3BzLmZsb29yXV0sXG4gIFsnRnVzZWRDb252JywgW2NvbnYsIHBhcnNlQ29udkF0dHJpYnV0ZXNdXSxcbiAgWydHYXRoZXInLCBbZ2F0aGVyLCBwYXJzZUdhdGhlckF0dHJpYnV0ZXNdXSxcbiAgWydHYXRoZXJFbGVtZW50cycsIFtnYXRoZXJFbGVtZW50cywgcGFyc2VHYXRoZXJFbGVtZW50c0F0dHJpYnV0ZXNdXSxcbiAgWydHYXRoZXJCbG9ja1F1YW50aXplZCcsIFtnYXRoZXJCbG9ja1F1YW50aXplZCwgcGFyc2VHYXRoZXJCbG9ja1F1YW50aXplZEF0dHJpYnV0ZXNdXSxcbiAgWydHYXRoZXJORCcsIFtnYXRoZXJORCwgcGFyc2VHYXRoZXJOREF0dHJpYnV0ZXNdXSxcbiAgWydHZWx1JywgW3VuYXJ5T3BzLmdlbHVdXSxcbiAgWydHZW1tJywgW2dlbW0sIHBhcnNlR2VtbUF0dHJpYnV0ZXNdXSxcbiAgWydHbG9iYWxBdmVyYWdlUG9vbCcsIFtwb29sLmdsb2JhbEF2ZXJhZ2VQb29sLCBwb29sLnBhcnNlR2xvYmFsQXZlcmFnZVBvb2xBdHRyaWJ1dGVzXV0sXG4gIFsnR2xvYmFsTWF4UG9vbCcsIFtwb29sLmdsb2JhbE1heFBvb2wsIHBvb2wucGFyc2VHbG9iYWxNYXhQb29sQXR0cmlidXRlc11dLFxuICBbJ0dyZWF0ZXInLCBbYmluYXJ5T3BzLmdyZWF0ZXJdXSxcbiAgWydHcmVhdGVyT3JFcXVhbCcsIFtiaW5hcnlPcHMuZ3JlYXRlck9yRXF1YWxdXSxcbiAgWydHcmlkU2FtcGxlJywgW2dyaWRTYW1wbGUsIHBhcnNlR3JpZFNhbXBsZUF0dHJpYnV0ZXNdXSxcbiAgWydHcm91cFF1ZXJ5QXR0ZW50aW9uJywgW2dyb3VwUXVlcnlBdHRlbnRpb25dXSxcbiAgWydIYXJkU2lnbW9pZCcsIFt1bmFyeU9wcy5oYXJkU2lnbW9pZCwgdW5hcnlPcHMucGFyc2VIYXJkU2lnbW9pZEF0dHJpYnV0ZXNdXSxcbiAgWydJbnN0YW5jZU5vcm1hbGl6YXRpb24nLCBbaW5zdGFuY2VOb3JtXV0sXG4gIFsnTGF5ZXJOb3JtYWxpemF0aW9uJywgW2xheWVyTm9ybV1dLFxuICBbJ0xlYWt5UmVsdScsIFt1bmFyeU9wcy5sZWFreVJlbHUsIHVuYXJ5T3BzLnBhcnNlQWxwaGFBdHRyaWJ1dGVzXV0sXG4gIFsnTGVzcycsIFtiaW5hcnlPcHMubGVzc11dLFxuICBbJ0xlc3NPckVxdWFsJywgW2JpbmFyeU9wcy5sZXNzT3JFcXVhbF1dLFxuICBbJ0xvZycsIFt1bmFyeU9wcy5sb2ddXSxcbiAgWydNYXRNdWwnLCBbbWF0TXVsXV0sXG4gIFsnTWF0TXVsTkJpdHMnLCBbbWF0TXVsTkJpdHMsIHBhcnNlTWF0TXVsTkJpdHNBdHRyaWJ1dGVzXV0sXG4gIC8vIFRPRE86IHN1cHBvcnQgbmV3IGF0dHJpYnV0ZXMgZm9yIE1heFBvb2wtOCBhbmQgTWF4UG9vbC0xMFxuICBbJ01heFBvb2wnLCBbcG9vbC5tYXhQb29sLCBwb29sLnBhcnNlTWF4UG9vbEF0dHJpYnV0ZXNdXSxcbiAgWydNdWwnLCBbYmluYXJ5T3BzLm11bF1dLFxuICBbJ011bHRpSGVhZEF0dGVudGlvbicsIFttdWx0aUhlYWRBdHRlbnRpb24sIHBhcnNlTXVsdGlIZWFkQXR0ZW50aW9uQXR0cmlidXRlc11dLFxuICBbJ05lZycsIFt1bmFyeU9wcy5uZWddXSxcbiAgWydOb3QnLCBbdW5hcnlPcHMubm90XV0sXG4gIFsnUGFkJywgW3BhZF1dLFxuICBbJ1BvdycsIFtiaW5hcnlPcHMucG93XV0sXG4gIFsnUXVpY2tHZWx1JywgW3VuYXJ5T3BzLnF1aWNrZ2VsdSwgdW5hcnlPcHMucGFyc2VBbHBoYUF0dHJpYnV0ZXNdXSxcbiAgWydSYW5nZScsIFtyYW5nZV1dLFxuICBbJ1JlY2lwcm9jYWwnLCBbdW5hcnlPcHMucmVjaXByb2NhbF1dLFxuICBbJ1JlZHVjZU1pbicsIFtyZWR1Y2VNaW5dXSxcbiAgWydSZWR1Y2VNZWFuJywgW3JlZHVjZU1lYW5dXSxcbiAgWydSZWR1Y2VNYXgnLCBbcmVkdWNlTWF4XV0sXG4gIFsnUmVkdWNlU3VtJywgW3JlZHVjZVN1bV1dLFxuICBbJ1JlZHVjZVByb2QnLCBbcmVkdWNlUHJvZF1dLFxuICBbJ1JlZHVjZUwxJywgW3JlZHVjZUwxXV0sXG4gIFsnUmVkdWNlTDInLCBbcmVkdWNlTDJdXSxcbiAgWydSZWR1Y2VMb2dTdW0nLCBbcmVkdWNlTG9nU3VtXV0sXG4gIFsnUmVkdWNlTG9nU3VtRXhwJywgW3JlZHVjZUxvZ1N1bUV4cF1dLFxuICBbJ1JlZHVjZVN1bVNxdWFyZScsIFtyZWR1Y2VTdW1TcXVhcmVdXSxcbiAgWydSZWx1JywgW3VuYXJ5T3BzLnJlbHVdXSxcbiAgWydSZXNpemUnLCBbcmVzaXplLCBwYXJzZVJlc2l6ZUF0dHJpYnV0ZXNdXSxcbiAgWydSb3RhcnlFbWJlZGRpbmcnLCBbcm90YXJ5RW1iZWRkaW5nXV0sXG4gIFsnU2NhdHRlck5EJywgW3NjYXR0ZXJORCwgcGFyc2VTY2F0dGVyTkRBdHRyaWJ1dGVzXV0sXG4gIFsnU2lnbW9pZCcsIFt1bmFyeU9wcy5zaWdtb2lkXV0sXG4gIFsnU2luJywgW3VuYXJ5T3BzLnNpbl1dLFxuICBbJ1NpbmgnLCBbdW5hcnlPcHMuc2luaF1dLFxuICBbJ1NsaWNlJywgW3NsaWNlLCBwYXJzZVNsaWNlQXR0cmlidXRlc11dLFxuICBbJ1NraXBMYXllck5vcm1hbGl6YXRpb24nLCBbc2tpcExheWVyTm9ybV1dLFxuICBbJ1NwbGl0JywgW3NwbGl0LCBwYXJzZVNwbGl0QXR0cmlidXRlc11dLFxuICBbJ1NxcnQnLCBbdW5hcnlPcHMuc3FydF1dLFxuICBbJ1NvZnRtYXgnLCBbc29mdG1heCwgcGFyc2VTb2Z0bWF4QXR0cmlidXRlc11dLFxuICBbJ1N1YicsIFtiaW5hcnlPcHMuc3ViXV0sXG4gIFsnVGFuJywgW3VuYXJ5T3BzLnRhbl1dLFxuICBbJ1RhbmgnLCBbdW5hcnlPcHMudGFuaF1dLFxuICBbJ1RocmVzaG9sZGVkUmVsdScsIFt1bmFyeU9wcy50aHJlc2hvbGRlZFJlbHUsIHVuYXJ5T3BzLnBhcnNlQWxwaGFBdHRyaWJ1dGVzXV0sXG4gIFsnVGlsZScsIFt0aWxlXV0sXG4gIFsnVHJhbnNwb3NlJywgW3RyYW5zcG9zZSwgcGFyc2VUcmFuc3Bvc2VBdHRyaWJ1dGVzXV0sXG4gIFsnV2hlcmUnLCBbd2hlcmVdXSxcbl0pO1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBUUkFDRV9GVU5DX0JFR0lOLCBUUkFDRV9GVU5DX0VORCB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IFdlYkdwdUJhY2tlbmQgfSBmcm9tICcuLi9iYWNrZW5kLXdlYmdwdSc7XG5pbXBvcnQgeyBMT0dfREVCVUcgfSBmcm9tICcuLi9sb2cnO1xuXG5pbXBvcnQgeyBjcmVhdGVTaGFkZXJIZWxwZXIgfSBmcm9tICcuL29wcy9jb21tb24nO1xuaW1wb3J0IHsgQXJ0aWZhY3QsIEdwdURhdGEsIFByb2dyYW1JbmZvIH0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogUHJvZ3JhbU1hbmFnZXIgaXMgdGhlIG1haW4gY2xhc3MgYmVoaW5kIHJ1bm5pbmcgY29tcHV0YXRpb25zXG4gKiBJdCBidWlsZHMgUHJvZ3JhbUluZm8ncyBpbnRvIEFydGlmYWN0c1xuICogSXQgY29tcGlsZXMgZ2l2ZW4gUHJvZ3JhbUluZm8ncyBpbnRvIFdlYkdMIFByb3JhbXMgKGNhY2hlZCBhcyBBcnRpZmFjdHMpXG4gKiBVc2VzIHRoZSBhcnRpZmFjdCB0byBydW4gdGhlIGNvbXB1dGF0aW9uIGJ5IGNhbGxpbmcgRHJhdyBvblxuICogdGhlIFdlYkdMIGRyYXdpbmcgYnVmZmVyXG4gKiBQcm9ncmFtTWFuYWdlciBhdXRvbWF0aWNhbGx5IG1hcHMgKGJpbmRzKSBpbnB1dCB2YXJpYWJsZXMgdG8gdGhlaXJcbiAqIGNvcnJlc3BvbmRpbmcgTG9jYXRpb24ncyBpbiB0aGUgYmluYXJ5IHByb2dyYW1cbiAqL1xuZXhwb3J0IGNsYXNzIFByb2dyYW1NYW5hZ2VyIHtcbiAgcmVwbzogTWFwPHVua25vd24sIEFydGlmYWN0PjsgLy8gdGhpcyBzaG91bGQgYmUgcGVyLXNlc3Npb24gb2JqZWN0XG4gIGF0dHJpYnV0ZXNCb3VuZDogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGJhY2tlbmQ6IFdlYkdwdUJhY2tlbmQpIHtcbiAgICB0aGlzLnJlcG8gPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5hdHRyaWJ1dGVzQm91bmQgPSBmYWxzZTtcbiAgfVxuICBnZXRBcnRpZmFjdChrZXk6IHVua25vd24pOiBBcnRpZmFjdCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMucmVwby5nZXQoa2V5KTtcbiAgfVxuICBzZXRBcnRpZmFjdChrZXk6IHVua25vd24sIGFydGlmYWN0OiBBcnRpZmFjdCk6IHZvaWQge1xuICAgIHRoaXMucmVwby5zZXQoa2V5LCBhcnRpZmFjdCk7XG4gIH1cbiAgcnVuKFxuICAgIGJ1aWxkQXJ0aWZhY3Q6IEFydGlmYWN0LFxuICAgIGlucHV0czogR3B1RGF0YVtdLFxuICAgIG91dHB1dHM6IEdwdURhdGFbXSxcbiAgICBkaXNwYXRjaEdyb3VwOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICAgdW5pZm9ybUJ1ZmZlckJpbmRpbmc6IEdQVUJpbmRpbmdSZXNvdXJjZSB8IHVuZGVmaW5lZCxcbiAgKTogdm9pZCB7XG4gICAgVFJBQ0VfRlVOQ19CRUdJTihidWlsZEFydGlmYWN0LnByb2dyYW1JbmZvLm5hbWUpO1xuICAgIGNvbnN0IGRldmljZSA9IHRoaXMuYmFja2VuZC5kZXZpY2U7XG4gICAgY29uc3QgY29tcHV0ZVBhc3NFbmNvZGVyID0gdGhpcy5iYWNrZW5kLmdldENvbXB1dGVQYXNzRW5jb2RlcigpO1xuICAgIHRoaXMuYmFja2VuZC53cml0ZVRpbWVzdGFtcCh0aGlzLmJhY2tlbmQucGVuZGluZ0Rpc3BhdGNoTnVtYmVyICogMik7XG4gICAgY29uc3QgZW50cmllcyA9IFtdO1xuICAgIGZvciAoY29uc3QgaW5wdXQgb2YgaW5wdXRzKSB7XG4gICAgICBlbnRyaWVzLnB1c2goeyBiaW5kaW5nOiBlbnRyaWVzLmxlbmd0aCwgcmVzb3VyY2U6IHsgYnVmZmVyOiBpbnB1dC5idWZmZXIgfSB9KTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBvdXRwdXQgb2Ygb3V0cHV0cykge1xuICAgICAgZW50cmllcy5wdXNoKHsgYmluZGluZzogZW50cmllcy5sZW5ndGgsIHJlc291cmNlOiB7IGJ1ZmZlcjogb3V0cHV0LmJ1ZmZlciB9IH0pO1xuICAgIH1cbiAgICBpZiAodW5pZm9ybUJ1ZmZlckJpbmRpbmcpIHtcbiAgICAgIGVudHJpZXMucHVzaCh7IGJpbmRpbmc6IGVudHJpZXMubGVuZ3RoLCByZXNvdXJjZTogdW5pZm9ybUJ1ZmZlckJpbmRpbmcgfSk7XG4gICAgfVxuICAgIGNvbnN0IGJpbmRHcm91cCA9IGRldmljZS5jcmVhdGVCaW5kR3JvdXAoe1xuICAgICAgbGF5b3V0OiBidWlsZEFydGlmYWN0LmNvbXB1dGVQaXBlbGluZS5nZXRCaW5kR3JvdXBMYXlvdXQoMCksXG4gICAgICBlbnRyaWVzLFxuICAgICAgbGFiZWw6IGJ1aWxkQXJ0aWZhY3QucHJvZ3JhbUluZm8ubmFtZSxcbiAgICB9KTtcblxuICAgIGlmICh0aGlzLmJhY2tlbmQuc2Vzc2lvblN0YXR1cyA9PT0gJ2NhcHR1cmluZycpIHtcbiAgICAgIGNvbnN0IGNvbW1hbmRJbmZvID0ge1xuICAgICAgICBrZXJuZWxJZDogdGhpcy5iYWNrZW5kLmN1cnJlbnRLZXJuZWxJZCEsXG4gICAgICAgIGNvbXB1dGVQaXBlbGluZTogYnVpbGRBcnRpZmFjdC5jb21wdXRlUGlwZWxpbmUsXG4gICAgICAgIGJpbmRHcm91cCxcbiAgICAgICAgZGlzcGF0Y2hHcm91cCxcbiAgICAgIH07XG4gICAgICBjb25zdCBzZXNzaW9uQ29tbWFuZExpc3QgPSB0aGlzLmJhY2tlbmQuY2FwdHVyZWRDb21tYW5kTGlzdC5nZXQodGhpcy5iYWNrZW5kLmN1cnJlbnRTZXNzaW9uSWQhKTtcbiAgICAgIHNlc3Npb25Db21tYW5kTGlzdCEucHVzaChjb21tYW5kSW5mbyk7XG4gICAgfVxuXG4gICAgY29tcHV0ZVBhc3NFbmNvZGVyLnNldFBpcGVsaW5lKGJ1aWxkQXJ0aWZhY3QuY29tcHV0ZVBpcGVsaW5lKTtcbiAgICBjb21wdXRlUGFzc0VuY29kZXIuc2V0QmluZEdyb3VwKDAsIGJpbmRHcm91cCk7XG4gICAgY29tcHV0ZVBhc3NFbmNvZGVyLmRpc3BhdGNoV29ya2dyb3VwcyguLi5kaXNwYXRjaEdyb3VwKTtcbiAgICB0aGlzLmJhY2tlbmQud3JpdGVUaW1lc3RhbXAodGhpcy5iYWNrZW5kLnBlbmRpbmdEaXNwYXRjaE51bWJlciAqIDIgKyAxKTtcbiAgICB0aGlzLmJhY2tlbmQucGVuZGluZ0Rpc3BhdGNoTnVtYmVyKys7XG5cbiAgICBpZiAoXG4gICAgICB0aGlzLmJhY2tlbmQucGVuZGluZ0Rpc3BhdGNoTnVtYmVyID49IHRoaXMuYmFja2VuZC5tYXhEaXNwYXRjaE51bWJlciB8fFxuICAgICAgdGhpcy5iYWNrZW5kLnF1ZXJ5VHlwZSA9PT0gJ2F0LXBhc3NlcydcbiAgICApIHtcbiAgICAgIHRoaXMuYmFja2VuZC5lbmRDb21wdXRlUGFzcygpO1xuICAgIH1cbiAgICBpZiAodGhpcy5iYWNrZW5kLnBlbmRpbmdEaXNwYXRjaE51bWJlciA+PSB0aGlzLmJhY2tlbmQubWF4RGlzcGF0Y2hOdW1iZXIpIHtcbiAgICAgIHRoaXMuYmFja2VuZC5mbHVzaCgpO1xuICAgIH1cbiAgICBUUkFDRV9GVU5DX0VORChidWlsZEFydGlmYWN0LnByb2dyYW1JbmZvLm5hbWUpO1xuICB9XG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgLy8gdGhpcy5yZXBvLmZvckVhY2goYSA9PiB0aGlzLmdsQ29udGV4dC5kZWxldGVQcm9ncmFtKGEucHJvZ3JhbSkpO1xuICB9XG4gIGJ1aWxkKHByb2dyYW1JbmZvOiBQcm9ncmFtSW5mbywgbm9ybWFsaXplZERpc3BhdGNoR3JvdXBTaXplOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pOiBBcnRpZmFjdCB7XG4gICAgVFJBQ0VfRlVOQ19CRUdJTihwcm9ncmFtSW5mby5uYW1lKTtcbiAgICBjb25zdCBkZXZpY2UgPSB0aGlzLmJhY2tlbmQuZGV2aWNlO1xuICAgIGNvbnN0IGVuYWJsZURpcmVjdGl2ZXM6IHN0cmluZ1tdID0gW107XG5cbiAgICAvLyBFbmFibGUgV0dTTCBleHRlbnNpb25zIGJhc2VkIG9uIGF2YWlsYWJsZSBXZWJHUFUgZmVhdHVyZXNcbiAgICBjb25zdCBleHRlbnNpb25zSW5mbzogQXJyYXk8eyBmZWF0dXJlOiBHUFVGZWF0dXJlTmFtZTsgZXh0ZW5zaW9uOiBzdHJpbmcgfT4gPSBbXG4gICAgICB7IGZlYXR1cmU6ICdzaGFkZXItZjE2JywgZXh0ZW5zaW9uOiAnZjE2JyB9LFxuICAgICAgeyBmZWF0dXJlOiAnc3ViZ3JvdXBzJyBhcyBHUFVGZWF0dXJlTmFtZSwgZXh0ZW5zaW9uOiAnc3ViZ3JvdXBzJyB9LFxuICAgIF07XG4gICAgZXh0ZW5zaW9uc0luZm8uZm9yRWFjaCgoaW5mbykgPT4ge1xuICAgICAgaWYgKGRldmljZS5mZWF0dXJlcy5oYXMoaW5mby5mZWF0dXJlKSkge1xuICAgICAgICBlbmFibGVEaXJlY3RpdmVzLnB1c2goYGVuYWJsZSAke2luZm8uZXh0ZW5zaW9ufTtgKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGNvbnN0IHNoYWRlckhlbHBlciA9IGNyZWF0ZVNoYWRlckhlbHBlcihub3JtYWxpemVkRGlzcGF0Y2hHcm91cFNpemUsIHRoaXMuYmFja2VuZC5kZXZpY2UubGltaXRzKTtcbiAgICBjb25zdCB1c2VyQ29kZSA9IHByb2dyYW1JbmZvLmdldFNoYWRlclNvdXJjZShzaGFkZXJIZWxwZXIpO1xuICAgIGNvbnN0IGNvZGUgPSBgJHtlbmFibGVEaXJlY3RpdmVzLmpvaW4oJ1xcbicpfVxcbiR7c2hhZGVySGVscGVyLmFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbnN9XFxuJHt1c2VyQ29kZX1gO1xuICAgIGNvbnN0IHNoYWRlck1vZHVsZSA9IGRldmljZS5jcmVhdGVTaGFkZXJNb2R1bGUoeyBjb2RlLCBsYWJlbDogcHJvZ3JhbUluZm8ubmFtZSB9KTtcbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW1dlYkdQVV0gJHtwcm9ncmFtSW5mby5uYW1lfSBzaGFkZXIgY29kZTogJHtjb2RlfWApO1xuXG4gICAgY29uc3QgY29tcHV0ZVBpcGVsaW5lID0gZGV2aWNlLmNyZWF0ZUNvbXB1dGVQaXBlbGluZSh7XG4gICAgICBjb21wdXRlOiB7IG1vZHVsZTogc2hhZGVyTW9kdWxlLCBlbnRyeVBvaW50OiAnbWFpbicgfSxcbiAgICAgIGxheW91dDogJ2F1dG8nLFxuICAgICAgbGFiZWw6IHByb2dyYW1JbmZvLm5hbWUsXG4gICAgfSk7XG5cbiAgICBUUkFDRV9GVU5DX0VORChwcm9ncmFtSW5mby5uYW1lKTtcbiAgICByZXR1cm4geyBwcm9ncmFtSW5mbywgY29tcHV0ZVBpcGVsaW5lLCB1bmlmb3JtVmFyaWFibGVzSW5mbzogc2hhZGVySGVscGVyLnZhcmlhYmxlc0luZm8gfTtcbiAgfVxuXG4gIG5vcm1hbGl6ZURpc3BhdGNoR3JvdXBTaXplKFxuICAgIGRpc3BhdGNoR3JvdXA6IFJldHVyblR5cGU8UHJvZ3JhbUluZm9bJ2dldFJ1bkRhdGEnXT5bJ2Rpc3BhdGNoR3JvdXAnXSxcbiAgKTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdIHtcbiAgICBjb25zdCB4ID0gdHlwZW9mIGRpc3BhdGNoR3JvdXAgPT09ICdudW1iZXInID8gZGlzcGF0Y2hHcm91cCA6IGRpc3BhdGNoR3JvdXAueDtcbiAgICBjb25zdCB5ID0gdHlwZW9mIGRpc3BhdGNoR3JvdXAgPT09ICdudW1iZXInID8gMSA6IGRpc3BhdGNoR3JvdXAueSB8fCAxO1xuICAgIGNvbnN0IHogPSB0eXBlb2YgZGlzcGF0Y2hHcm91cCA9PT0gJ251bWJlcicgPyAxIDogZGlzcGF0Y2hHcm91cC56IHx8IDE7XG4gICAgY29uc3QgbGltaXRQZXJEaW1lbnNpb24gPSB0aGlzLmJhY2tlbmQuZGV2aWNlLmxpbWl0cy5tYXhDb21wdXRlV29ya2dyb3Vwc1BlckRpbWVuc2lvbjtcbiAgICBpZiAoeCA8PSBsaW1pdFBlckRpbWVuc2lvbiAmJiB5IDw9IGxpbWl0UGVyRGltZW5zaW9uICYmIHogPD0gbGltaXRQZXJEaW1lbnNpb24pIHtcbiAgICAgIHJldHVybiBbeCwgeSwgel07XG4gICAgfVxuICAgIGNvbnN0IHNpemUgPSB4ICogeSAqIHo7XG4gICAgbGV0IGRpc3BhdGNoQXZlcmFnZSA9IE1hdGguY2VpbChNYXRoLnNxcnQoc2l6ZSkpO1xuICAgIGlmIChkaXNwYXRjaEF2ZXJhZ2UgPiBsaW1pdFBlckRpbWVuc2lvbikge1xuICAgICAgZGlzcGF0Y2hBdmVyYWdlID0gTWF0aC5jZWlsKE1hdGguY2JydChzaXplKSk7XG4gICAgICBpZiAoZGlzcGF0Y2hBdmVyYWdlID4gbGltaXRQZXJEaW1lbnNpb24pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUb3RhbCBkaXNwYXRjaCBzaXplIGV4Y2VlZHMgV2ViR1BVIG1heGltdW0uJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gW2Rpc3BhdGNoQXZlcmFnZSwgZGlzcGF0Y2hBdmVyYWdlLCBkaXNwYXRjaEF2ZXJhZ2VdO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gW2Rpc3BhdGNoQXZlcmFnZSwgZGlzcGF0Y2hBdmVyYWdlLCAxXTtcbiAgICB9XG4gIH1cbn1cbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHsgRW52LCBUZW5zb3IsIFRSQUNFLCBUUkFDRV9GVU5DX0JFR0lOLCBUUkFDRV9GVU5DX0VORCB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IERhdGFUeXBlLCB0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyB9IGZyb20gJy4uL3dhc20tY29tbW9uJztcblxuaW1wb3J0IHsgY29uZmlndXJlTG9nZ2VyLCBMT0dfREVCVUcgfSBmcm9tICcuL2xvZyc7XG5pbXBvcnQgeyBjcmVhdGVWaWV3LCBUZW5zb3JWaWV3IH0gZnJvbSAnLi90ZW5zb3Itdmlldyc7XG5pbXBvcnQgeyBjcmVhdGVHcHVEYXRhTWFuYWdlciwgZG93bmxvYWRHcHVEYXRhLCBHcHVEYXRhTWFuYWdlciB9IGZyb20gJy4vd2ViZ3B1L2dwdS1kYXRhLW1hbmFnZXInO1xuaW1wb3J0IHsgUnVuRnVuY3Rpb24sIFdFQkdQVV9PUF9SRVNPTFZFX1JVTEVTIH0gZnJvbSAnLi93ZWJncHUvb3AtcmVzb2x2ZS1ydWxlcyc7XG5pbXBvcnQgeyBQcm9ncmFtTWFuYWdlciB9IGZyb20gJy4vd2ViZ3B1L3Byb2dyYW0tbWFuYWdlcic7XG5pbXBvcnQge1xuICBBZGFwdGVySW5mbyxcbiAgQ29tcHV0ZUNvbnRleHQsXG4gIEdwdUFyY2hpdGVjdHVyZSxcbiAgR3B1RGF0YSxcbiAgR3B1VmVuZG9yLFxuICBQcm9ncmFtSW5mbyxcbiAgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3ksXG4gIFNlc3Npb25TdGF0ZSxcbiAgVGltZXN0YW1wUXVlcnksXG59IGZyb20gJy4vd2ViZ3B1L3R5cGVzJztcblxuaW50ZXJmYWNlIENvbW1hbmRJbmZvIHtcbiAgcmVhZG9ubHkga2VybmVsSWQ6IG51bWJlcjtcbiAgcmVhZG9ubHkgY29tcHV0ZVBpcGVsaW5lOiBHUFVDb21wdXRlUGlwZWxpbmU7XG4gIHJlYWRvbmx5IGJpbmRHcm91cDogR1BVQmluZEdyb3VwO1xuICByZWFkb25seSBkaXNwYXRjaEdyb3VwOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG59XG5cbmludGVyZmFjZSBLZXJuZWxJbmZvIHtcbiAgcmVhZG9ubHkga2VybmVsVHlwZTogc3RyaW5nO1xuICByZWFkb25seSBrZXJuZWxOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGtlcm5lbEVudHJ5OiBSdW5GdW5jdGlvbjtcbiAgcmVhZG9ubHkgYXR0cmlidXRlczogWygoYXR0cmlidXRlOiB1bmtub3duKSA9PiB1bmtub3duKSB8IHVuZGVmaW5lZCwgdW5rbm93bl07XG59XG5cbmludGVyZmFjZSBQZW5kaW5nS2VybmVsSW5mbyB7XG4gIHJlYWRvbmx5IGtlcm5lbElkOiBudW1iZXI7XG4gIHJlYWRvbmx5IHByb2dyYW1OYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGlucHV0VGVuc29yVmlld3M6IHJlYWRvbmx5IFRlbnNvclZpZXdbXTtcbiAgcmVhZG9ubHkgb3V0cHV0VGVuc29yVmlld3M6IHJlYWRvbmx5IFRlbnNvclZpZXdbXTtcbn1cblxuY29uc3QgZ2V0UHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lLZXkgPSAoXG4gIGlucHV0VGVuc29yczogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICBpbnB1dERlcGVuZGVuY2llczogcmVhZG9ubHkgUHJvZ3JhbUlucHV0VGVuc29ySW5mb0RlcGVuZGVuY3lbXSxcbik6IHN0cmluZyA9PiB7XG4gIGlmIChpbnB1dERlcGVuZGVuY2llcy5sZW5ndGggIT09IGlucHV0VGVuc29ycy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgaW5wdXREZXBlbmRlbmNpZXMgbGVuZ3RoICR7aW5wdXREZXBlbmRlbmNpZXMubGVuZ3RofSBpcyBub3QgZXF1YWwgdG8gaW5wdXRUZW5zb3JzIGxlbmd0aCAke1xuICAgICAgICBpbnB1dFRlbnNvcnMubGVuZ3RoXG4gICAgICB9LmAsXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IGlucHV0SW5mb3M6IHN0cmluZ1tdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRUZW5zb3JzLmxlbmd0aDsgKytpKSB7XG4gICAgY29uc3QgdHlwZSA9IGlucHV0VGVuc29yc1tpXS5kYXRhVHlwZTtcbiAgICBzd2l0Y2ggKGlucHV0RGVwZW5kZW5jaWVzW2ldKSB7XG4gICAgICBjYXNlICdub25lJzoge1xuICAgICAgICBpbnB1dEluZm9zLnB1c2goJycpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ3R5cGUnOiB7XG4gICAgICAgIGlucHV0SW5mb3MucHVzaChgJHt0eXBlfWApO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ3JhbmsnOiB7XG4gICAgICAgIGNvbnN0IHJhbmsgPSBpbnB1dFRlbnNvcnNbaV0uZGltcy5sZW5ndGg7XG4gICAgICAgIGlucHV0SW5mb3MucHVzaChgJHt0eXBlfTske3Jhbmt9YCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAnZGltcyc6IHtcbiAgICAgICAgY29uc3QgZGltcyA9IGlucHV0VGVuc29yc1tpXS5kaW1zLmpvaW4oJywnKTtcbiAgICAgICAgaW5wdXRJbmZvcy5wdXNoKGAke3R5cGV9OyR7ZGltc31gKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGlucHV0IGRlcGVuZGVuY3k6ICR7aW5wdXREZXBlbmRlbmNpZXNbaV19YCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGlucHV0SW5mb3Muam9pbignfCcpO1xufTtcblxuLyoqXG4gKiBnZXQgYSB1bmlxdWUga2V5IHJlcHJlc2VudGluZyB0aGUgcHJvZ3JhbSBmcm9tIHRoZSBwcm9ncmFtIGluZm8sIGlucHV0IHNoYXBlcyBhbmQgdHlwZXMuXG4gKlxuICogQHJldHVybnMgYSB1bmlxdWUga2V5IGlzIGEgc2hvcnRlciBzdHJpbmcgdGhhbiB0aGUgc2hhZGVyIHNvdXJjZSwgd2hpY2ggY29udGFpbnMgYWxsIHRoZSBpbmZvcm1hdGlvbiB0byBpZGVudGlmeSBhXG4gKiBwcm9ncmFtLiBpZiB0aGUga2V5IGlzIHRoZSBzYW1lLCB0aGUgcHJvZ3JhbSBzaGFkZXIgc291cmNlIHNob3VsZCBiZSB0aGUgc2FtZSwgc28gd2UgY2FuIHJldXNlIHRoZSBwcm9ncmFtLlxuICpcbiAqL1xuY29uc3QgZ2V0UHJvZ3JhbUluZm9VbmlxdWVLZXkgPSAoXG4gIHByb2dyYW1JbmZvOiBQcm9ncmFtSW5mbyxcbiAgaW5wdXRUZW5zb3JzOiByZWFkb25seSBUZW5zb3JWaWV3W10sXG4gIGlzMURpbWVuc2lvbkRpc3BhdGNoOiBib29sZWFuLFxuKTogc3RyaW5nID0+IHtcbiAgLy8gZmluYWwga2V5IGZvcm1hdDpcbiAgLy8gPFBST0dSQU1fTkFNRT5bPFBST0dSQU1fQ1VTVE9NX0NBQ0hFX0hJTlQ+XTppczFEaW1lbnNpb25EaXNwYXRjaDo8SU5QVVRTX0lORk9fMD58PElOUFVUU19JTkZPXzE+fC4uLlxuICBsZXQga2V5ID0gcHJvZ3JhbUluZm8ubmFtZTtcbiAgaWYgKHByb2dyYW1JbmZvLnNoYWRlckNhY2hlPy5oaW50KSB7XG4gICAga2V5ICs9ICdbJyArIHByb2dyYW1JbmZvLnNoYWRlckNhY2hlLmhpbnQgKyAnXSc7XG4gIH1cbiAga2V5ICs9XG4gICAgJzonICtcbiAgICBpczFEaW1lbnNpb25EaXNwYXRjaCArXG4gICAgYDoke2dldFByb2dyYW1JbnB1dFRlbnNvckluZm9EZXBlbmRlbmN5S2V5KFxuICAgICAgaW5wdXRUZW5zb3JzLFxuICAgICAgcHJvZ3JhbUluZm8uc2hhZGVyQ2FjaGU/LmlucHV0RGVwZW5kZW5jaWVzID8/XG4gICAgICAgIG5ldyBBcnJheTxQcm9ncmFtSW5wdXRUZW5zb3JJbmZvRGVwZW5kZW5jeT4oaW5wdXRUZW5zb3JzLmxlbmd0aCkuZmlsbCgnZGltcycpLFxuICAgICl9YDtcbiAgcmV0dXJuIGtleTtcbn07XG5cbmNsYXNzIEFkYXB0ZXJJbmZvSW1wbCBpbXBsZW1lbnRzIEFkYXB0ZXJJbmZvIHtcbiAgcmVhZG9ubHkgYXJjaGl0ZWN0dXJlPzogc3RyaW5nO1xuICByZWFkb25seSB2ZW5kb3I/OiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoYWRhcHRlckluZm86IEdQVUFkYXB0ZXJJbmZvKSB7XG4gICAgaWYgKGFkYXB0ZXJJbmZvKSB7XG4gICAgICB0aGlzLmFyY2hpdGVjdHVyZSA9IGFkYXB0ZXJJbmZvLmFyY2hpdGVjdHVyZTtcbiAgICAgIHRoaXMudmVuZG9yID0gYWRhcHRlckluZm8udmVuZG9yO1xuICAgIH1cbiAgfVxuXG4gIGlzQXJjaGl0ZWN0dXJlKGFyY2hpdGVjdHVyZTogR3B1QXJjaGl0ZWN0dXJlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuYXJjaGl0ZWN0dXJlID09PSBhcmNoaXRlY3R1cmU7XG4gIH1cblxuICBpc1ZlbmRvcih2ZW5kb3I6IEdwdVZlbmRvcik6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnZlbmRvciA9PT0gdmVuZG9yO1xuICB9XG59XG5cbi8qKlxuICogdGhpcyBjbGFzcyBpcyBkZXNpZ25lZCB0byBzdG9yZSBzdGF0dXMgYW5kIGJlaW5nIHVzZWQgYXMgYSBzaW5nbGV0b24gZm9yIEpTRVAuIEl0IHdpbGwgYmUgcGFzc2VkIHRvIGpzZXBJbml0KCkgYXNcbiAqIHRoZSBmaXJzdCBwYXJhbWV0ZXIgc28gdGhhdCBpdCBpcyBzdG9yZWQgZm9yIGZ1dHVyZSB1c2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJHcHVCYWNrZW5kIHtcbiAgYWRhcHRlckluZm86IEFkYXB0ZXJJbmZvSW1wbDtcbiAgZGV2aWNlOiBHUFVEZXZpY2U7XG4gIC8qKlxuICAgKiBhbiBpbnN0YW5jZSBvZiBHcHVEYXRhTWFuYWdlciB0byBtYW5hZ2UgYSBHcHVEYXRhSWQgLT4gR3B1QnVmZmVyIG1hcHBpbmdcbiAgICovXG4gIGdwdURhdGFNYW5hZ2VyOiBHcHVEYXRhTWFuYWdlcjtcbiAgLyoqXG4gICAqIGFuIGluc3RhbmNlIG9mIFByb2dyYW1NYW5hZ2VyIHRvIGJ1aWxkIGFuZCBydW4gV2ViR1BVIGNvbXB1dGUgc2hhZGVyIHByb2dyYW0sIGFuZCBtYW5hZ2UgYSBQcm9ncmFtS2V5IC0+IFByb2dyYW1cbiAgICogYXJ0aWZhY3RzIG1hcHBpbmdcbiAgICovXG4gIHByb2dyYW1NYW5hZ2VyOiBQcm9ncmFtTWFuYWdlcjtcblxuICAvKipcbiAgICogcmVwcmVzZW50aW5nIHRoZSBzZXNzaW9uIElEIG9mIHdoaWNoIGlzIGN1cnJlbnRseSBiZWluZyBydW4uXG4gICAqIGBudWxsYCBtZWFucyBubyBzZXNzaW9uIGlzIGJlaW5nIHJ1bi5cbiAgICogb25seSB2YWxpZCB3aGVuIHNlc3Npb24ucnVuIGlzIGV4ZWN1dGVkLlxuICAgKi9cbiAgY3VycmVudFNlc3Npb25JZDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIHJlcHJlc2VudGluZyB0aGUga2VybmVsIElEIG9mIHdoaWNoIGlzIGN1cnJlbnRseSBiZWluZyBjb21wdXRlZCAoQ1BVIGNvZGUgcGVyc3BlY3RpdmUpLlxuICAgKiBgbnVsbGAgbWVhbnMgbm8ga2VybmVsIGlzIGJlaW5nIGNvbXB1dGVkLlxuICAgKiBvbmx5IG9uZSBrZXJuZWwgY2FuIGJlIGNvbXB1dGVkIGF0IGEgbW9tZW50LlxuICAgKi9cbiAgY3VycmVudEtlcm5lbElkOiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqXG4gICAqIGEgbGlzdCBvZiB0ZW1wb3JhcnkgR1BVIGRhdGEgZm9yIHRoZSBjdXJyZW50IGtlcm5lbC4gc2hvdWxkIHJlbGVhc2Ugd2hlbiB0aGUga2VybmVsIGRvbmUgY29tcHV0YXRpb24uXG4gICAqL1xuICBwcml2YXRlIHRlbXBvcmFyeURhdGE6IEdwdURhdGFbXTtcbiAgLyoqXG4gICAqIGEgS2VybmVsSUQgLT4gYSBHUFUgZGF0YSBsaXN0LCB3aGljaCBzdG9yZXMgcGVyc2lzdGVudCBHUFUgZGF0YSBvd25lZCBieSB0aGUgc3BlY2lmaWMga2VybmVsLlxuICAgKi9cbiAgcHJpdmF0ZSBrZXJuZWxQZXJzaXN0ZW50RGF0YTogTWFwPG51bWJlciwgR3B1RGF0YVtdPjtcbiAgLyoqXG4gICAqIGEgS2VybmVsSUQgLT4gYSBjdXN0b20gZGF0YSwgd2hpY2ggc3RvcmVzIGN1c3RvbSBkYXRhIG93bmVkIGJ5IHRoZSBzcGVjaWZpYyBrZXJuZWwuXG4gICAqL1xuICBwcml2YXRlIGtlcm5lbEN1c3RvbURhdGE6IE1hcDxudW1iZXIsIHsgW2tleTogc3RyaW5nXTogdW5rbm93biB9PjtcbiAgLyoqXG4gICAqIGdldCB0aGUgY3VzdG9tIGRhdGEgb2YgdGhlIGN1cnJlbnQga2VybmVsXG4gICAqL1xuICBnZXQgY3VycmVudEtlcm5lbEN1c3RvbURhdGEoKTogeyBba2V5OiBzdHJpbmddOiB1bmtub3duIH0ge1xuICAgIGlmICh0aGlzLmN1cnJlbnRLZXJuZWxJZCA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjdXJyZW50S2VybmVsQ3VzdG9tRGF0YSgpOiBjdXJyZW50S2VybmVsSWQgaXMgbnVsbC4gKHNob3VsZCBub3QgaGFwcGVuKScpO1xuICAgIH1cblxuICAgIGxldCBkYXRhID0gdGhpcy5rZXJuZWxDdXN0b21EYXRhLmdldCh0aGlzLmN1cnJlbnRLZXJuZWxJZCk7XG4gICAgaWYgKCFkYXRhKSB7XG4gICAgICBkYXRhID0ge307XG4gICAgICB0aGlzLmtlcm5lbEN1c3RvbURhdGEuc2V0KHRoaXMuY3VycmVudEtlcm5lbElkLCBkYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIC8vIEtlcm5lbElEIC0+IGtlcm5lbEluZm8gbWFwcGluZ1xuICBrZXJuZWxzOiBNYXA8bnVtYmVyLCBLZXJuZWxJbmZvPjtcbiAgcHJpdmF0ZSBjb21tYW5kRW5jb2RlcjogR1BVQ29tbWFuZEVuY29kZXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBjb21wdXRlUGFzc0VuY29kZXI6IEdQVUNvbXB1dGVQYXNzRW5jb2RlciB8IG51bGwgPSBudWxsO1xuICBtYXhEaXNwYXRjaE51bWJlciA9IDE2O1xuICBwZW5kaW5nRGlzcGF0Y2hOdW1iZXIgPSAwO1xuXG4gIC8vIGluZm8gb2Yga2VybmVscyBwZW5kaW5nIHN1Ym1pc3Npb24gZm9yIGEgc2luZ2xlIGJhdGNoXG4gIHByaXZhdGUgcGVuZGluZ0tlcm5lbHM6IFBlbmRpbmdLZXJuZWxJbmZvW10gPSBbXTtcbiAgLy8gcXVlcnlSZWFkQnVmZmVyIC0+IHBlbmRpbmdLZXJuZWxzIG1hcHBpbmcgZm9yIGFsbCB0aGUgYmF0Y2hlc1xuICBwcml2YXRlIHBlbmRpbmdRdWVyaWVzOiBNYXA8R1BVQnVmZmVyLCBQZW5kaW5nS2VybmVsSW5mb1tdPiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBxdWVyeVJlc29sdmVCdWZmZXI/OiBHUFVCdWZmZXI7XG4gIHByaXZhdGUgcXVlcnlTZXQ/OiBHUFVRdWVyeVNldDtcbiAgcHJpdmF0ZSBxdWVyeVRpbWVCYXNlPzogYmlnaW50O1xuICBxdWVyeVR5cGU6IFRpbWVzdGFtcFF1ZXJ5O1xuXG4gIGVudjogRW52O1xuICBzZXNzaW9uU3RhdHVzOiBTZXNzaW9uU3RhdGUgPSAnZGVmYXVsdCc7XG4gIC8qKlxuICAgKiBhIFNlc3Npb25JRCAtPiBDb21tYW5kSW5mb1tdIG1hcHBpbmcuIEl0J3MgdXNlZCB0byByZWNvcmQgYWxsIEdQVSBjb21tYW5kcyBmb3IgY29ycmVzcG9uZGluZyBzZXNzaW9uLlxuICAgKi9cbiAgY2FwdHVyZWRDb21tYW5kTGlzdDogTWFwPG51bWJlciwgQ29tbWFuZEluZm9bXT4gPSBuZXcgTWFwKCk7XG5cbiAgLyoqXG4gICAqIGEgU2Vzc2lvbklEIC0+IFBlbmRpbmdLZXJuZWxJbmZvW10gbWFwcGluZyBmb3IgcHJvZmlsaW5nLlxuICAgKi9cbiAgcHJpdmF0ZSBjYXB0dXJlZFBlbmRpbmdLZXJuZWxzOiBNYXA8bnVtYmVyLCBQZW5kaW5nS2VybmVsSW5mb1tdPiA9IG5ldyBNYXAoKTtcblxuICAvKipcbiAgICogYSBTZXNzaW9uSUQgLT4gYSBNYXAgb2YgKElucHV0T3V0cHV0SW5kZXggLT4gW0lELCBHUFVCdWZmZXJdKSBtYXBwaW5nLlxuICAgKi9cbiAgc2Vzc2lvbkV4dGVybmFsRGF0YU1hcHBpbmc6IE1hcDxudW1iZXIsIE1hcDxudW1iZXIsIFtudW1iZXIsIEdQVUJ1ZmZlcl0+PiA9IG5ldyBNYXAoKTtcblxuICBhc3luYyBpbml0aWFsaXplKGVudjogRW52LCBhZGFwdGVyOiBHUFVBZGFwdGVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5lbnYgPSBlbnY7XG4gICAgY29uc3QgcmVxdWlyZWRGZWF0dXJlczogR1BVRmVhdHVyZU5hbWVbXSA9IFtdO1xuICAgIGNvbnN0IGRldmljZURlc2NyaXB0b3I6IEdQVURldmljZURlc2NyaXB0b3IgPSB7XG4gICAgICByZXF1aXJlZExpbWl0czoge1xuICAgICAgICBtYXhDb21wdXRlV29ya2dyb3VwU3RvcmFnZVNpemU6IGFkYXB0ZXIubGltaXRzLm1heENvbXB1dGVXb3JrZ3JvdXBTdG9yYWdlU2l6ZSxcbiAgICAgICAgbWF4Q29tcHV0ZVdvcmtncm91cHNQZXJEaW1lbnNpb246IGFkYXB0ZXIubGltaXRzLm1heENvbXB1dGVXb3JrZ3JvdXBzUGVyRGltZW5zaW9uLFxuICAgICAgICBtYXhTdG9yYWdlQnVmZmVyQmluZGluZ1NpemU6IGFkYXB0ZXIubGltaXRzLm1heFN0b3JhZ2VCdWZmZXJCaW5kaW5nU2l6ZSxcbiAgICAgICAgbWF4QnVmZmVyU2l6ZTogYWRhcHRlci5saW1pdHMubWF4QnVmZmVyU2l6ZSxcbiAgICAgICAgbWF4Q29tcHV0ZUludm9jYXRpb25zUGVyV29ya2dyb3VwOiBhZGFwdGVyLmxpbWl0cy5tYXhDb21wdXRlSW52b2NhdGlvbnNQZXJXb3JrZ3JvdXAsXG4gICAgICAgIG1heENvbXB1dGVXb3JrZ3JvdXBTaXplWDogYWRhcHRlci5saW1pdHMubWF4Q29tcHV0ZVdvcmtncm91cFNpemVYLFxuICAgICAgICBtYXhDb21wdXRlV29ya2dyb3VwU2l6ZVk6IGFkYXB0ZXIubGltaXRzLm1heENvbXB1dGVXb3JrZ3JvdXBTaXplWSxcbiAgICAgICAgbWF4Q29tcHV0ZVdvcmtncm91cFNpemVaOiBhZGFwdGVyLmxpbWl0cy5tYXhDb21wdXRlV29ya2dyb3VwU2l6ZVosXG4gICAgICB9LFxuICAgICAgcmVxdWlyZWRGZWF0dXJlcyxcbiAgICB9O1xuXG4gICAgLy8gVHJ5IHJlcXVpcmluZyBXZWJHUFUgZmVhdHVyZXNcbiAgICBjb25zdCByZXF1aXJlRmVhdHVyZUlmQXZhaWxhYmxlID0gKGZlYXR1cmU6IEdQVUZlYXR1cmVOYW1lKSA9PlxuICAgICAgYWRhcHRlci5mZWF0dXJlcy5oYXMoZmVhdHVyZSkgJiYgcmVxdWlyZWRGZWF0dXJlcy5wdXNoKGZlYXR1cmUpICYmIHRydWU7XG4gICAgLy8gVHJ5IGNocm9taXVtLWV4cGVyaW1lbnRhbC10aW1lc3RhbXAtcXVlcnktaW5zaWRlLXBhc3NlcyBhbmQgZmFsbGJhY2sgdG8gdGltZXN0YW1wLXF1ZXJ5XG4gICAgaWYgKCFyZXF1aXJlRmVhdHVyZUlmQXZhaWxhYmxlKCdjaHJvbWl1bS1leHBlcmltZW50YWwtdGltZXN0YW1wLXF1ZXJ5LWluc2lkZS1wYXNzZXMnIGFzIEdQVUZlYXR1cmVOYW1lKSkge1xuICAgICAgcmVxdWlyZUZlYXR1cmVJZkF2YWlsYWJsZSgndGltZXN0YW1wLXF1ZXJ5Jyk7XG4gICAgfVxuICAgIHJlcXVpcmVGZWF0dXJlSWZBdmFpbGFibGUoJ3NoYWRlci1mMTYnKTtcbiAgICAvLyBUcnkgc3ViZ3JvdXBzXG4gICAgcmVxdWlyZUZlYXR1cmVJZkF2YWlsYWJsZSgnc3ViZ3JvdXBzJyBhcyBHUFVGZWF0dXJlTmFtZSk7XG5cbiAgICB0aGlzLmRldmljZSA9IGF3YWl0IGFkYXB0ZXIucmVxdWVzdERldmljZShkZXZpY2VEZXNjcmlwdG9yKTtcbiAgICB0aGlzLmFkYXB0ZXJJbmZvID0gbmV3IEFkYXB0ZXJJbmZvSW1wbChhZGFwdGVyLmluZm8gfHwgKGF3YWl0IGFkYXB0ZXIucmVxdWVzdEFkYXB0ZXJJbmZvKCkpKTtcbiAgICB0aGlzLmdwdURhdGFNYW5hZ2VyID0gY3JlYXRlR3B1RGF0YU1hbmFnZXIodGhpcyk7XG4gICAgdGhpcy5wcm9ncmFtTWFuYWdlciA9IG5ldyBQcm9ncmFtTWFuYWdlcih0aGlzKTtcbiAgICB0aGlzLmtlcm5lbHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5rZXJuZWxQZXJzaXN0ZW50RGF0YSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmtlcm5lbEN1c3RvbURhdGEgPSBuZXcgTWFwKCk7XG5cbiAgICAvLyBzZXQgdXAgZmxhZ3MgZm9yIGxvZ2dlclxuICAgIGNvbmZpZ3VyZUxvZ2dlcihlbnYubG9nTGV2ZWwhLCAhIWVudi5kZWJ1Zyk7XG5cbiAgICAvLyBUT0RPOiBzZXQgdXAgZmxhZ3NcblxuICAgIHRoaXMuZGV2aWNlLm9udW5jYXB0dXJlZGVycm9yID0gKGV2KSA9PiB7XG4gICAgICBpZiAoZXYuZXJyb3IgaW5zdGFuY2VvZiBHUFVWYWxpZGF0aW9uRXJyb3IpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS5lcnJvcihgQW4gdW5jYXVnaHQgV2ViR1BVIHZhbGlkYXRpb24gZXJyb3Igd2FzIHJhaXNlZDogJHtldi5lcnJvci5tZXNzYWdlfWApO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcy5lbnYud2ViZ3B1LCAnZGV2aWNlJywge1xuICAgICAgdmFsdWU6IHRoaXMuZGV2aWNlLFxuICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMuZW52LndlYmdwdSwgJ2FkYXB0ZXInLCB7XG4gICAgICB2YWx1ZTogYWRhcHRlcixcbiAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgIH0pO1xuXG4gICAgLy8gaW5pdCBxdWVyeVR5cGUsIHdoaWNoIGlzIG5lY2Vzc2FyeSBmb3IgSW5mZXJlbmNlU2Vzc2lvbi5jcmVhdGVcbiAgICB0aGlzLnNldFF1ZXJ5VHlwZSgpO1xuICB9XG5cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICBpZiAodHlwZW9mIHRoaXMucXVlcnlTZXQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLnF1ZXJ5U2V0LmRlc3Ryb3koKTtcbiAgICB9XG4gICAgdGhpcy5ncHVEYXRhTWFuYWdlci5kaXNwb3NlKCk7XG4gIH1cblxuICBnZXRDb21tYW5kRW5jb2RlcigpOiBHUFVDb21tYW5kRW5jb2RlciB7XG4gICAgaWYgKCF0aGlzLmNvbW1hbmRFbmNvZGVyKSB7XG4gICAgICB0aGlzLmNvbW1hbmRFbmNvZGVyID0gdGhpcy5kZXZpY2UuY3JlYXRlQ29tbWFuZEVuY29kZXIoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY29tbWFuZEVuY29kZXI7XG4gIH1cblxuICBnZXRDb21wdXRlUGFzc0VuY29kZXIoKTogR1BVQ29tcHV0ZVBhc3NFbmNvZGVyIHtcbiAgICBpZiAoIXRoaXMuY29tcHV0ZVBhc3NFbmNvZGVyKSB7XG4gICAgICBjb25zdCBjb21tYW5kRW5jb2RlciA9IHRoaXMuZ2V0Q29tbWFuZEVuY29kZXIoKTtcbiAgICAgIGNvbnN0IGNvbXB1dGVQYXNzRGVzY3JpcHRvcjogR1BVQ29tcHV0ZVBhc3NEZXNjcmlwdG9yID0ge307XG5cbiAgICAgIGlmICh0aGlzLnF1ZXJ5VHlwZSA9PT0gJ2F0LXBhc3NlcycpIHtcbiAgICAgICAgY29tcHV0ZVBhc3NEZXNjcmlwdG9yLnRpbWVzdGFtcFdyaXRlcyA9IHtcbiAgICAgICAgICBxdWVyeVNldDogdGhpcy5xdWVyeVNldCEsXG4gICAgICAgICAgYmVnaW5uaW5nT2ZQYXNzV3JpdGVJbmRleDogdGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgKiAyLFxuICAgICAgICAgIGVuZE9mUGFzc1dyaXRlSW5kZXg6IHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyICogMiArIDEsXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY29tcHV0ZVBhc3NFbmNvZGVyID0gY29tbWFuZEVuY29kZXIuYmVnaW5Db21wdXRlUGFzcyhjb21wdXRlUGFzc0Rlc2NyaXB0b3IpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jb21wdXRlUGFzc0VuY29kZXI7XG4gIH1cblxuICBlbmRDb21wdXRlUGFzcygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jb21wdXRlUGFzc0VuY29kZXIpIHtcbiAgICAgIHRoaXMuY29tcHV0ZVBhc3NFbmNvZGVyLmVuZCgpO1xuICAgICAgdGhpcy5jb21wdXRlUGFzc0VuY29kZXIgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGZsdXNoKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jb21tYW5kRW5jb2Rlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIFRSQUNFX0ZVTkNfQkVHSU4oKTtcblxuICAgIHRoaXMuZW5kQ29tcHV0ZVBhc3MoKTtcbiAgICBsZXQgcXVlcnlSZWFkQnVmZmVyOiBHUFVCdWZmZXI7XG4gICAgaWYgKHRoaXMucXVlcnlUeXBlICE9PSAnbm9uZScpIHtcbiAgICAgIHRoaXMuY29tbWFuZEVuY29kZXIucmVzb2x2ZVF1ZXJ5U2V0KFxuICAgICAgICB0aGlzLnF1ZXJ5U2V0ISxcbiAgICAgICAgMCxcbiAgICAgICAgdGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgKiAyLFxuICAgICAgICB0aGlzLnF1ZXJ5UmVzb2x2ZUJ1ZmZlciEsXG4gICAgICAgIDAsXG4gICAgICApO1xuXG4gICAgICBxdWVyeVJlYWRCdWZmZXIgPSB0aGlzLmRldmljZS5jcmVhdGVCdWZmZXIoXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgICAgIHsgc2l6ZTogdGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgKiAyICogOCwgdXNhZ2U6IEdQVUJ1ZmZlclVzYWdlLk1BUF9SRUFEIHwgR1BVQnVmZmVyVXNhZ2UuQ09QWV9EU1QgfSxcbiAgICAgICk7XG5cbiAgICAgIHRoaXMucGVuZGluZ1F1ZXJpZXMuc2V0KHF1ZXJ5UmVhZEJ1ZmZlciwgdGhpcy5wZW5kaW5nS2VybmVscyk7XG4gICAgICB0aGlzLnBlbmRpbmdLZXJuZWxzID0gW107XG4gICAgICB0aGlzLmNvbW1hbmRFbmNvZGVyLmNvcHlCdWZmZXJUb0J1ZmZlcihcbiAgICAgICAgdGhpcy5xdWVyeVJlc29sdmVCdWZmZXIhLFxuICAgICAgICAwLFxuICAgICAgICBxdWVyeVJlYWRCdWZmZXIsXG4gICAgICAgIDAsXG4gICAgICAgIHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyICogMiAqIDgsXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMuZGV2aWNlLnF1ZXVlLnN1Ym1pdChbdGhpcy5jb21tYW5kRW5jb2Rlci5maW5pc2goKV0pO1xuICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIucmVmcmVzaFBlbmRpbmdCdWZmZXJzKCk7XG4gICAgdGhpcy5jb21tYW5kRW5jb2RlciA9IG51bGw7XG4gICAgdGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgPSAwO1xuXG4gICAgaWYgKHRoaXMucXVlcnlUeXBlICE9PSAnbm9uZScpIHtcbiAgICAgIHZvaWQgcXVlcnlSZWFkQnVmZmVyIS5tYXBBc3luYyhHUFVNYXBNb2RlLlJFQUQpLnRoZW4oKCkgPT4ge1xuICAgICAgICBjb25zdCBtYXBwZWREYXRhID0gbmV3IEJpZ1VpbnQ2NEFycmF5KHF1ZXJ5UmVhZEJ1ZmZlci5nZXRNYXBwZWRSYW5nZSgpKTtcbiAgICAgICAgY29uc3QgcGVuZGluZ0tlcm5lbHMgPSB0aGlzLnBlbmRpbmdRdWVyaWVzLmdldChxdWVyeVJlYWRCdWZmZXIpITtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXBwZWREYXRhLmxlbmd0aCAvIDI7IGkrKykge1xuICAgICAgICAgIGNvbnN0IHBlbmRpbmdLZXJuZWxJbmZvID0gcGVuZGluZ0tlcm5lbHNbaV07XG4gICAgICAgICAgY29uc3Qga2VybmVsSWQgPSBwZW5kaW5nS2VybmVsSW5mby5rZXJuZWxJZDtcbiAgICAgICAgICBjb25zdCBrZXJuZWxJbmZvID0gdGhpcy5rZXJuZWxzLmdldChrZXJuZWxJZCkhO1xuICAgICAgICAgIGNvbnN0IGtlcm5lbFR5cGUgPSBrZXJuZWxJbmZvLmtlcm5lbFR5cGU7XG4gICAgICAgICAgY29uc3Qga2VybmVsTmFtZSA9IGtlcm5lbEluZm8ua2VybmVsTmFtZTtcbiAgICAgICAgICBjb25zdCBwcm9ncmFtTmFtZSA9IHBlbmRpbmdLZXJuZWxJbmZvLnByb2dyYW1OYW1lO1xuICAgICAgICAgIGNvbnN0IGlucHV0VGVuc29yVmlld3MgPSBwZW5kaW5nS2VybmVsSW5mby5pbnB1dFRlbnNvclZpZXdzO1xuICAgICAgICAgIGNvbnN0IG91dHB1dFRlbnNvclZpZXdzID0gcGVuZGluZ0tlcm5lbEluZm8ub3V0cHV0VGVuc29yVmlld3M7XG4gICAgICAgICAgY29uc3Qgc3RhcnRUaW1lVTY0ID0gbWFwcGVkRGF0YVtpICogMl07XG4gICAgICAgICAgY29uc3QgZW5kVGltZVU2NCA9IG1hcHBlZERhdGFbaSAqIDIgKyAxXTtcblxuICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5xdWVyeVRpbWVCYXNlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdGhpcy5xdWVyeVRpbWVCYXNlID0gc3RhcnRUaW1lVTY0O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IE51bWJlcihzdGFydFRpbWVVNjQgLSB0aGlzLnF1ZXJ5VGltZUJhc2UpO1xuICAgICAgICAgIGNvbnN0IGVuZFRpbWUgPSBOdW1iZXIoZW5kVGltZVU2NCAtIHRoaXMucXVlcnlUaW1lQmFzZSk7XG5cbiAgICAgICAgICBpZiAoIU51bWJlci5pc1NhZmVJbnRlZ2VyKHN0YXJ0VGltZSkgfHwgIU51bWJlci5pc1NhZmVJbnRlZ2VyKGVuZFRpbWUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignaW5jb3JyZWN0IHRpbWVzdGFtcCByYW5nZScpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0aGlzLmVudi53ZWJncHUucHJvZmlsaW5nPy5vbmRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMuZW52LndlYmdwdS5wcm9maWxpbmcub25kYXRhKHtcbiAgICAgICAgICAgICAgdmVyc2lvbjogMSxcbiAgICAgICAgICAgICAgaW5wdXRzTWV0YWRhdGE6IGlucHV0VGVuc29yVmlld3MubWFwKCh2YWx1ZSkgPT4gKHtcbiAgICAgICAgICAgICAgICBkaW1zOiB2YWx1ZS5kaW1zLFxuICAgICAgICAgICAgICAgIGRhdGFUeXBlOiB0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyh2YWx1ZS5kYXRhVHlwZSksXG4gICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgICAgb3V0cHV0c01ldGFkYXRhOiBvdXRwdXRUZW5zb3JWaWV3cy5tYXAoKHZhbHVlKSA9PiAoe1xuICAgICAgICAgICAgICAgIGRpbXM6IHZhbHVlLmRpbXMsXG4gICAgICAgICAgICAgICAgZGF0YVR5cGU6IHRlbnNvckRhdGFUeXBlRW51bVRvU3RyaW5nKHZhbHVlLmRhdGFUeXBlKSxcbiAgICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgICBrZXJuZWxJZCxcbiAgICAgICAgICAgICAga2VybmVsVHlwZSxcbiAgICAgICAgICAgICAga2VybmVsTmFtZSxcbiAgICAgICAgICAgICAgcHJvZ3JhbU5hbWUsXG4gICAgICAgICAgICAgIHN0YXJ0VGltZSxcbiAgICAgICAgICAgICAgZW5kVGltZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBpZiBubyBjYWxsYmFjayBpcyBwcm92aWRlZCwgcHJpbnQgdGhlIHByb2ZpbGluZyBtZXNzYWdlIHRvIGNvbnNvbGVcbiAgICAgICAgICAgIGxldCBpbnB1dFNoYXBlcyA9ICcnO1xuICAgICAgICAgICAgaW5wdXRUZW5zb3JWaWV3cy5mb3JFYWNoKCh2YWx1ZSwgaSkgPT4ge1xuICAgICAgICAgICAgICBpbnB1dFNoYXBlcyArPSBgaW5wdXRbJHtpfV06IFske3ZhbHVlLmRpbXN9XSB8ICR7dGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcodmFsdWUuZGF0YVR5cGUpfSwgYDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgbGV0IG91dHB1dFNoYXBlcyA9ICcnO1xuICAgICAgICAgICAgb3V0cHV0VGVuc29yVmlld3MuZm9yRWFjaCgodmFsdWUsIGkpID0+IHtcbiAgICAgICAgICAgICAgb3V0cHV0U2hhcGVzICs9IGBvdXRwdXRbJHtpfV06IFske3ZhbHVlLmRpbXN9XSB8ICR7dGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcodmFsdWUuZGF0YVR5cGUpfSwgYDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICBgW3Byb2ZpbGluZ10ga2VybmVsIFwiJHtrZXJuZWxJZH18JHtrZXJuZWxUeXBlfXwke2tlcm5lbE5hbWV9fCR7cHJvZ3JhbU5hbWV9XCIgJHtpbnB1dFNoYXBlc30ke1xuICAgICAgICAgICAgICAgIG91dHB1dFNoYXBlc1xuICAgICAgICAgICAgICB9ZXhlY3V0aW9uIHRpbWU6ICR7ZW5kVGltZSAtIHN0YXJ0VGltZX0gbnNgLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgVFJBQ0UoJ0dQVScsIGAke3Byb2dyYW1OYW1lfTo6JHtzdGFydFRpbWVVNjR9Ojoke2VuZFRpbWVVNjR9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcXVlcnlSZWFkQnVmZmVyLnVubWFwKCk7XG4gICAgICAgIHRoaXMucGVuZGluZ1F1ZXJpZXMuZGVsZXRlKHF1ZXJ5UmVhZEJ1ZmZlcik7XG4gICAgICB9KTtcbiAgICB9XG4gICAgVFJBQ0VfRlVOQ19FTkQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBydW4gYSBXZWJHUFUgcHJvZ3JhbS5cbiAgICogQHBhcmFtIHByb2dyYW0gYSBQcm9ncmFtSW5mbyBpbnN0YW5jZVxuICAgKiBAcGFyYW0gaW5wdXRUZW5zb3JWaWV3cyBhIFRlbnNvclZpZXcgYXJyYXkuIGVhY2ggZWxlbWVudCByZXByZXNlbnRzIGEgdmFsdWUgYWxyZWFkeSBleGlzdHMgaW4gR1BVLlxuICAgKiBAcGFyYW0gb3V0cHV0SW5kaWNlcyBhbiBpbmRpY2VzIGFycmF5LiBlYWNoIGVsZW1lbnQgY2FuIGJlIGVpdGhlciAtMSAodGVtcG9yYXJ5IGRhdGEpLCAtMiAocGVyc2lzdGVudCBkYXRhKSBvciBhblxuICAgKiBpbmRleCB0byB0aGUga2VybmVsJ3Mgb3V0cHV0LlxuICAgKiBAcGFyYW0gY3JlYXRlS2VybmVsT3V0cHV0IGEgY2FsbGJhY2sgZnVuY3Rpb24gdGhhdCBjcmVhdGUgYSB2YWx1ZSB0byBrZXJuZWwncyBvdXRwdXQgd2l0aCB0aGUgZ2l2ZW4gaW5kZXhcbiAgICogQHBhcmFtIGNyZWF0ZUludGVybWVkaWF0ZU91dHB1dCBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgY3JlYXRlIGEgdmFsdWUgYXMgYSBpbnRlcm1lZGlhdGUgdmFsdWUsIGVpdGhlciB0ZW1wb3JhcnlcbiAgICogb3IgcGVyc2lzdGVudCAob3duZWQgYnkgdGhlIGN1cnJlbnQga2VybmVsKVxuICAgKiBAcmV0dXJucyBhIFRlbnNvclZpZXcgYXJyYXkgcmVwcmVzZW50aW5nIHRoZSByZXN1bHQuXG4gICAqL1xuICBydW4oXG4gICAgcHJvZ3JhbTogUHJvZ3JhbUluZm8sXG4gICAgaW5wdXRUZW5zb3JWaWV3czogcmVhZG9ubHkgVGVuc29yVmlld1tdLFxuICAgIG91dHB1dEluZGljZXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGNyZWF0ZUtlcm5lbE91dHB1dDogKGluZGV4OiBudW1iZXIsIGRhdGFUeXBlOiBudW1iZXIsIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKSA9PiBUZW5zb3JWaWV3LFxuICAgIGNyZWF0ZUludGVybWVkaWF0ZU91dHB1dDogKGRhdGFUeXBlOiBudW1iZXIsIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKSA9PiBUZW5zb3JWaWV3LFxuICAgIG91dHB1dENvdW50OiBudW1iZXIsXG4gICk6IFRlbnNvclZpZXdbXSB7XG4gICAgVFJBQ0VfRlVOQ19CRUdJTihwcm9ncmFtLm5hbWUpO1xuICAgIC8vIGNyZWF0ZSBpbmZvIGZvciBpbnB1dHNcbiAgICBjb25zdCBpbnB1dERhdGFzOiBHcHVEYXRhW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0VGVuc29yVmlld3MubGVuZ3RoOyArK2kpIHtcbiAgICAgIGNvbnN0IGRhdGEgPSBpbnB1dFRlbnNvclZpZXdzW2ldLmRhdGE7XG4gICAgICAvLyBpZiB0ZW5zb3IgdmlldyBkYXRhIGlzIDAsIGl0IG1lYW5zIHRoZSBvdXRwdXQgaXMgemVyby1zaXplZCB0ZW5zb3IsIGFuZCB0aGVyZSBpcyBubyBHUFUgZGF0YSBmb3IgaXQuXG4gICAgICBpZiAoZGF0YSA9PT0gMCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGdwdURhdGEgPSB0aGlzLmdwdURhdGFNYW5hZ2VyLmdldChkYXRhKTtcbiAgICAgIGlmICghZ3B1RGF0YSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vIEdQVSBkYXRhIGZvciBpbnB1dDogJHtkYXRhfWApO1xuICAgICAgfVxuICAgICAgaW5wdXREYXRhcy5wdXNoKGdwdURhdGEpO1xuICAgIH1cblxuICAgIGNvbnN0IHsgb3V0cHV0cywgZGlzcGF0Y2hHcm91cCwgcHJvZ3JhbVVuaWZvcm1zIH0gPSBwcm9ncmFtLmdldFJ1bkRhdGEoaW5wdXRUZW5zb3JWaWV3cyk7XG5cbiAgICAvLyBjaGVjayBvdXRwdXQgaW5kaWNlc1xuICAgIGNvbnN0IHZhbGlkYXRlZE91dHB1dEluZGljZXMgPSBvdXRwdXRJbmRpY2VzLmxlbmd0aCA9PT0gMCA/IG91dHB1dHMubWFwKChfLCBpKSA9PiBpKSA6IG91dHB1dEluZGljZXM7XG4gICAgaWYgKHZhbGlkYXRlZE91dHB1dEluZGljZXMubGVuZ3RoICE9PSBvdXRwdXRzLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBPdXRwdXQgc2l6ZSAke3ZhbGlkYXRlZE91dHB1dEluZGljZXMubGVuZ3RofSBtdXN0IGJlIGVxdWFsIHRvICR7b3V0cHV0cy5sZW5ndGh9LmApO1xuICAgIH1cblxuICAgIC8vIGNyZWF0ZSBpbmZvIGZvciBvdXRwdXRzXG4gICAgY29uc3Qgb3V0cHV0VGVuc29yVmlld3M6IFRlbnNvclZpZXdbXSA9IFtdO1xuICAgIGNvbnN0IG91dHB1dERhdGFzOiBHcHVEYXRhW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG91dHB1dHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIC8vIHZhbHVlIC0xIGFuZCAtMiBhcmUgdXNlZCBmb3IgY3JlYXRpbmcgdGVtcG9yYXJ5IGFuZCBwZXJzaXN0ZW50IG91dHB1dHMuXG4gICAgICAvLyB2YWx1ZSAtMyBpcyB1c2VkIGZvciBwbGFjZWhvbGRlciBvdXRwdXQuIFNvIC0zLCAtMiwgLTEgYW5kIDAsIDEsIDIsIC4uLiBhcmUgdmFsaWRcbiAgICAgIC8vIG91dHB1dCBpbmRpY2VzLiBzZWUgdHlwZSBkZWZpbml0aW9uIG9mIENvbXB1dGVDb250ZXh0SW5wdXRzT3V0cHV0c01hcHBpbmcgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgIGlmIChcbiAgICAgICAgIU51bWJlci5pc0ludGVnZXIodmFsaWRhdGVkT3V0cHV0SW5kaWNlc1tpXSkgfHxcbiAgICAgICAgdmFsaWRhdGVkT3V0cHV0SW5kaWNlc1tpXSA8IC0zIHx8XG4gICAgICAgIHZhbGlkYXRlZE91dHB1dEluZGljZXNbaV0gPj0gb3V0cHV0Q291bnRcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgb3V0cHV0IGluZGV4OiAke3ZhbGlkYXRlZE91dHB1dEluZGljZXNbaV19YCk7XG4gICAgICB9XG4gICAgICBpZiAodmFsaWRhdGVkT3V0cHV0SW5kaWNlc1tpXSA9PT0gLTMpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCBpc1RlbXBvcmFyeSA9IHZhbGlkYXRlZE91dHB1dEluZGljZXNbaV0gPT09IC0xO1xuICAgICAgY29uc3QgaXNQZXJzaXN0ZW50ID0gdmFsaWRhdGVkT3V0cHV0SW5kaWNlc1tpXSA9PT0gLTI7XG4gICAgICBjb25zdCB0ZW5zb3JWaWV3ID1cbiAgICAgICAgaXNUZW1wb3JhcnkgfHwgaXNQZXJzaXN0ZW50XG4gICAgICAgICAgPyBjcmVhdGVJbnRlcm1lZGlhdGVPdXRwdXQob3V0cHV0c1tpXS5kYXRhVHlwZSwgb3V0cHV0c1tpXS5kaW1zKVxuICAgICAgICAgIDogY3JlYXRlS2VybmVsT3V0cHV0KHZhbGlkYXRlZE91dHB1dEluZGljZXNbaV0sIG91dHB1dHNbaV0uZGF0YVR5cGUsIG91dHB1dHNbaV0uZGltcyk7XG4gICAgICBvdXRwdXRUZW5zb3JWaWV3cy5wdXNoKHRlbnNvclZpZXcpO1xuICAgICAgLy8gaWYgdGVuc29yIHZpZXcgZGF0YSBpcyAwLCBpdCBtZWFucyB0aGUgb3V0cHV0IGlzIHplcm8tc2l6ZWQgdGVuc29yLCBhbmQgdGhlcmUgaXMgbm8gR1BVIGRhdGEgZm9yIGl0LlxuICAgICAgaWYgKHRlbnNvclZpZXcuZGF0YSA9PT0gMCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGdwdURhdGEgPSB0aGlzLmdwdURhdGFNYW5hZ2VyLmdldCh0ZW5zb3JWaWV3LmRhdGEpO1xuICAgICAgaWYgKCFncHVEYXRhKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbm8gR1BVIGRhdGEgZm9yIG91dHB1dDogJHt0ZW5zb3JWaWV3LmRhdGF9YCk7XG4gICAgICB9XG4gICAgICBpZiAoaXNUZW1wb3JhcnkpIHtcbiAgICAgICAgdGhpcy50ZW1wb3JhcnlEYXRhLnB1c2goZ3B1RGF0YSk7XG4gICAgICB9XG4gICAgICBpZiAoaXNQZXJzaXN0ZW50KSB7XG4gICAgICAgIGxldCBwZXJzaXN0ZW50RGF0YSA9IHRoaXMua2VybmVsUGVyc2lzdGVudERhdGEuZ2V0KHRoaXMuY3VycmVudEtlcm5lbElkISk7XG4gICAgICAgIGlmICghcGVyc2lzdGVudERhdGEpIHtcbiAgICAgICAgICBwZXJzaXN0ZW50RGF0YSA9IFtdO1xuICAgICAgICAgIHRoaXMua2VybmVsUGVyc2lzdGVudERhdGEuc2V0KHRoaXMuY3VycmVudEtlcm5lbElkISwgcGVyc2lzdGVudERhdGEpO1xuICAgICAgICB9XG4gICAgICAgIHBlcnNpc3RlbnREYXRhLnB1c2goZ3B1RGF0YSk7XG4gICAgICB9XG4gICAgICBvdXRwdXREYXRhcy5wdXNoKGdwdURhdGEpO1xuICAgIH1cblxuICAgIC8vIHdoZW4gdGhlcmUgYXJlIGFueSB6ZXJvLXNpemVkIHRlbnNvciBpbiB0aGUgaW5wdXRzIG9yIG91dHB1dHMsIHdlIHNob3VsZCByZXBvcnQgZXJyb3IgdW5sZXNzIGFsbCBvdXRwdXRzIGFyZVxuICAgIC8vIHplcm8tc2l6ZWQgdGVuc29ycy5cbiAgICBpZiAoaW5wdXREYXRhcy5sZW5ndGggIT09IGlucHV0VGVuc29yVmlld3MubGVuZ3RoIHx8IG91dHB1dERhdGFzLmxlbmd0aCAhPT0gb3V0cHV0VGVuc29yVmlld3MubGVuZ3RoKSB7XG4gICAgICAvLyBpZiBhbGwgb3V0cHV0cyBhcmUgemVyby1zaXplZCB0ZW5zb3JzLCB0aGVyZSBpcyBubyBuZWVkIHRvIHJ1biB0aGUgcHJvZ3JhbS5cbiAgICAgIGlmIChvdXRwdXREYXRhcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgVFJBQ0VfRlVOQ19FTkQocHJvZ3JhbS5uYW1lKTtcbiAgICAgICAgcmV0dXJuIG91dHB1dFRlbnNvclZpZXdzO1xuICAgICAgfVxuICAgICAgLy8gaWYgc29tZSBvdXRwdXRzIGFyZSB6ZXJvLXNpemVkIHRlbnNvcnMsIHJlcG9ydCBhbiBlcnJvci5cbiAgICAgIC8vXG4gICAgICAvLyBUT0RPOiBzbyBmYXIgd2UgZG9uJ3Qgc2VlIGFueSB1c2UgY2FzZSB0aGF0IG91dHB1dHMgaW5jbHVkZSBib3RoIHplcm8tc2l6ZWQgdGVuc29ycyBhbmQgbm9uLXplcm8tc2l6ZWQgdGVuc29ycy5cbiAgICAgIC8vIElmIHdlIHNlZSBzdWNoIHVzZSBjYXNlLCB3ZSBuZWVkIHRvIG1ha2UgYSBjaGFuZ2UgaGVyZSB0byBzdXBwb3J0IGl0LlxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgUHJvZ3JhbSAke3Byb2dyYW0ubmFtZX0gaGFzIHplcm8tc2l6ZWQgdGVuc29yKHMpIGluIGlucHV0cyBvciBvdXRwdXRzLiBUaGlzIGlzIG5vdCBzdXBwb3J0ZWQgbm93LmAsXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIGxvYWQgdW5pZm9ybXNcbiAgICAvLyBUT0RPOiBhZGQgY2FjaGUgZm9yIHVuaWZvcm0gKGlzIGl0IG5lY2Vzc2FyeT8pXG4gICAgLy9cbiAgICBsZXQgdW5pZm9ybUJ1ZmZlckJpbmRpbmc6IEdQVUJpbmRpbmdSZXNvdXJjZSB8IHVuZGVmaW5lZDtcbiAgICBpZiAocHJvZ3JhbVVuaWZvcm1zKSB7XG4gICAgICBsZXQgY3VycmVudE9mZnNldCA9IDA7XG4gICAgICBjb25zdCBvZmZzZXRzOiBudW1iZXJbXSA9IFtdO1xuXG4gICAgICBwcm9ncmFtVW5pZm9ybXMuZm9yRWFjaCgodikgPT4ge1xuICAgICAgICBjb25zdCBkYXRhID0gdHlwZW9mIHYuZGF0YSA9PT0gJ251bWJlcicgPyBbdi5kYXRhXSA6IHYuZGF0YTtcbiAgICAgICAgaWYgKGRhdGEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGh0dHBzOi8vd3d3LnczLm9yZy9UUi9XR1NMLyNhbGlnbm9mXG4gICAgICAgIGNvbnN0IHNpemVPZkVsZW1lbnQgPSB2LnR5cGUgPT09IERhdGFUeXBlLmZsb2F0MTYgPyAyIDogNDtcbiAgICAgICAgbGV0IHNpemVPZlZlY09yTWF0O1xuICAgICAgICBsZXQgYmFzZUFsaWdubWVudDtcbiAgICAgICAgaWYgKHYudHlwZSA9PT0gRGF0YVR5cGUuZmxvYXQxNikge1xuICAgICAgICAgIGJhc2VBbGlnbm1lbnQgPSBkYXRhLmxlbmd0aCA+IDQgPyAxNiA6IGRhdGEubGVuZ3RoID4gMiA/IDggOiBkYXRhLmxlbmd0aCAqIHNpemVPZkVsZW1lbnQ7XG4gICAgICAgICAgc2l6ZU9mVmVjT3JNYXQgPSBkYXRhLmxlbmd0aCA+IDQgPyAxNiA6IHNpemVPZkVsZW1lbnQgKiBkYXRhLmxlbmd0aDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBiYXNlQWxpZ25tZW50ID0gZGF0YS5sZW5ndGggPD0gMiA/IGRhdGEubGVuZ3RoICogc2l6ZU9mRWxlbWVudCA6IDE2O1xuICAgICAgICAgIHNpemVPZlZlY09yTWF0ID0gMTY7XG4gICAgICAgIH1cbiAgICAgICAgY3VycmVudE9mZnNldCA9IE1hdGguY2VpbChjdXJyZW50T2Zmc2V0IC8gYmFzZUFsaWdubWVudCkgKiBiYXNlQWxpZ25tZW50O1xuICAgICAgICBvZmZzZXRzLnB1c2goY3VycmVudE9mZnNldCk7XG4gICAgICAgIC8vIEZvciBub24tZmxvYXQxNiB0eXBlLCB3aGVuIGRhdGEubGVuZ3RoID4gNCwgdGhlIHVuaWZvcm0gdmFyaWFibGUgaXMgb2YgdHlwZSBhcnJheTx2ZWM0PGkzMnx1MzJ8ZjMyPixOPiwgd2hlcmVcbiAgICAgICAgLy8gTiA9IE1hdGguY2VpbChkYXRhLmxlbmd0aCAvIDQpIGFuZCBTaXplT2YodmVjNDxpMzJ8dTMyfGYzMj4pID0gMTYuIFRoZSB0b3RhbCBieXRlIGxlbmd0aCBpcyBOICpcbiAgICAgICAgLy8gU2l6ZU9mKHZlYzQ8aTMyfHUzMnxmMzI+KS4gRm9yIGZsb2F0MTYgdHlwZSwgd2hlbiBkYXRhLmxlbmd0aCA+IDQsIHRoZSB1bmlmb3JtIHZhcmlhYmxlIGlzIG9mIHR5cGVcbiAgICAgICAgLy8gYXJyYXk8bWF0Mng0PGYxNj4sTj4sIHdoZXJlIE4gPSBNYXRoLmNlaWwoZGF0YS5sZW5ndGggLyA4KSBhbmQgU2l6ZU9mKG1hdDJ4NDxmMTY+KSA9IDE2LiBUaGUgdG90YWwgYnl0ZVxuICAgICAgICAvLyBsZW5ndGggaXMgTiAqIFNpemVPZihtYXQyeDQ8ZjE2PikuXG4gICAgICAgIGNvbnN0IGVsZW1lbnRQZXJWZWNPck1hdCA9IHYudHlwZSA9PT0gRGF0YVR5cGUuZmxvYXQxNiA/IDggOiA0O1xuICAgICAgICBjdXJyZW50T2Zmc2V0ICs9XG4gICAgICAgICAgZGF0YS5sZW5ndGggPiA0ID8gTWF0aC5jZWlsKGRhdGEubGVuZ3RoIC8gZWxlbWVudFBlclZlY09yTWF0KSAqIHNpemVPZlZlY09yTWF0IDogZGF0YS5sZW5ndGggKiBzaXplT2ZFbGVtZW50O1xuICAgICAgfSk7XG5cbiAgICAgIC8vIE1lZXQgYWxpZ25tZW50IG9mIHN0cnVjdCBoZXJlOiBodHRwczovL3d3dy53My5vcmcvVFIvV0dTTC8jYWxpZ25tZW50LWFuZC1zaXplLiBGb3Igc2ltcGxpY2l0eSwgc2V0XG4gICAgICAvLyBtYXhBbGlnbm1lbnRPZkZpZWxkIHRvIDE2IHNpbmNlIHRoZSB1bmRlcmx5aW5nIGJ1ZmZlciBoYXMgYmVlbiByb3VuZGVkIHVwIHRvIDE2LlxuICAgICAgY29uc3QgbWF4QWxpZ25tZW50T2ZGaWVsZCA9IDE2O1xuICAgICAgY3VycmVudE9mZnNldCA9IE1hdGguY2VpbChjdXJyZW50T2Zmc2V0IC8gbWF4QWxpZ25tZW50T2ZGaWVsZCkgKiBtYXhBbGlnbm1lbnRPZkZpZWxkO1xuICAgICAgY29uc3QgYXJyYXlCdWZmZXIgPSBuZXcgQXJyYXlCdWZmZXIoY3VycmVudE9mZnNldCk7XG4gICAgICBwcm9ncmFtVW5pZm9ybXMuZm9yRWFjaCgodiwgaSkgPT4ge1xuICAgICAgICBjb25zdCBvZmZzZXQgPSBvZmZzZXRzW2ldO1xuICAgICAgICBjb25zdCBkYXRhID0gdHlwZW9mIHYuZGF0YSA9PT0gJ251bWJlcicgPyBbdi5kYXRhXSA6IHYuZGF0YTtcbiAgICAgICAgaWYgKHYudHlwZSA9PT0gRGF0YVR5cGUuaW50MzIpIHtcbiAgICAgICAgICBuZXcgSW50MzJBcnJheShhcnJheUJ1ZmZlciwgb2Zmc2V0LCBkYXRhLmxlbmd0aCkuc2V0KGRhdGEpO1xuICAgICAgICB9IGVsc2UgaWYgKHYudHlwZSA9PT0gRGF0YVR5cGUudWludDMyKSB7XG4gICAgICAgICAgbmV3IFVpbnQzMkFycmF5KGFycmF5QnVmZmVyLCBvZmZzZXQsIGRhdGEubGVuZ3RoKS5zZXQoZGF0YSk7XG4gICAgICAgIH0gZWxzZSBpZiAodi50eXBlID09PSBEYXRhVHlwZS5mbG9hdDE2KSB7XG4gICAgICAgICAgbmV3IFVpbnQxNkFycmF5KGFycmF5QnVmZmVyLCBvZmZzZXQsIGRhdGEubGVuZ3RoKS5zZXQoZGF0YSk7XG4gICAgICAgIH0gZWxzZSBpZiAodi50eXBlID09PSBEYXRhVHlwZS5mbG9hdCkge1xuICAgICAgICAgIG5ldyBGbG9hdDMyQXJyYXkoYXJyYXlCdWZmZXIsIG9mZnNldCwgZGF0YS5sZW5ndGgpLnNldChkYXRhKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIHVuaWZvcm0gdHlwZTogJHt0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyh2LnR5cGUpfWApO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdW5pZm9ybUJ1ZmZlckRhdGEgPVxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgICAgICB0aGlzLmdwdURhdGFNYW5hZ2VyLmNyZWF0ZShjdXJyZW50T2Zmc2V0LCBHUFVCdWZmZXJVc2FnZS5DT1BZX0RTVCB8IEdQVUJ1ZmZlclVzYWdlLlVOSUZPUk0pO1xuICAgICAgdGhpcy5kZXZpY2UucXVldWUud3JpdGVCdWZmZXIodW5pZm9ybUJ1ZmZlckRhdGEuYnVmZmVyLCAwLCBhcnJheUJ1ZmZlciwgMCwgY3VycmVudE9mZnNldCk7XG4gICAgICB0aGlzLmdwdURhdGFNYW5hZ2VyLnJlbGVhc2UodW5pZm9ybUJ1ZmZlckRhdGEuaWQpO1xuICAgICAgdW5pZm9ybUJ1ZmZlckJpbmRpbmcgPSB7IG9mZnNldDogMCwgc2l6ZTogY3VycmVudE9mZnNldCwgYnVmZmVyOiB1bmlmb3JtQnVmZmVyRGF0YS5idWZmZXIgfTtcbiAgICB9XG5cbiAgICBjb25zdCBub3JtYWxpemVkRGlzcGF0Y2hHcm91cCA9IHRoaXMucHJvZ3JhbU1hbmFnZXIubm9ybWFsaXplRGlzcGF0Y2hHcm91cFNpemUoZGlzcGF0Y2hHcm91cCk7XG4gICAgY29uc3QgaXMxRGltZW5zaW9uRGlzcGF0Y2ggPSBub3JtYWxpemVkRGlzcGF0Y2hHcm91cFsxXSA9PT0gMSAmJiBub3JtYWxpemVkRGlzcGF0Y2hHcm91cFsyXSA9PT0gMTtcbiAgICAvLyBnZXQgcHJvZ3JhbSBpbmZvXG4gICAgY29uc3Qga2V5ID0gZ2V0UHJvZ3JhbUluZm9VbmlxdWVLZXkocHJvZ3JhbSwgaW5wdXRUZW5zb3JWaWV3cywgaXMxRGltZW5zaW9uRGlzcGF0Y2gpO1xuICAgIGxldCBhcnRpZmFjdCA9IHRoaXMucHJvZ3JhbU1hbmFnZXIuZ2V0QXJ0aWZhY3Qoa2V5KTtcbiAgICBpZiAoIWFydGlmYWN0KSB7XG4gICAgICBhcnRpZmFjdCA9IHRoaXMucHJvZ3JhbU1hbmFnZXIuYnVpbGQocHJvZ3JhbSwgbm9ybWFsaXplZERpc3BhdGNoR3JvdXApO1xuICAgICAgdGhpcy5wcm9ncmFtTWFuYWdlci5zZXRBcnRpZmFjdChrZXksIGFydGlmYWN0KTtcbiAgICAgIExPR19ERUJVRygnaW5mbycsICgpID0+IGBbYXJ0aWZhY3RdIGtleTogJHtrZXl9LCBwcm9ncmFtTmFtZTogJHtwcm9ncmFtLm5hbWV9YCk7XG4gICAgfVxuXG4gICAgLy8gdmFsaWRhdGUgdW5pZm9ybSB2YXJpYWJsZXNcbiAgICBpZiAocHJvZ3JhbVVuaWZvcm1zICYmIGFydGlmYWN0LnVuaWZvcm1WYXJpYWJsZXNJbmZvKSB7XG4gICAgICBpZiAocHJvZ3JhbVVuaWZvcm1zLmxlbmd0aCAhPT0gYXJ0aWZhY3QudW5pZm9ybVZhcmlhYmxlc0luZm8ubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgVW5pZm9ybSB2YXJpYWJsZXMgY291bnQgbWlzbWF0Y2g6IGV4cGVjdCAke2FydGlmYWN0LnVuaWZvcm1WYXJpYWJsZXNJbmZvLmxlbmd0aH0sIGdvdCAke1xuICAgICAgICAgICAgcHJvZ3JhbVVuaWZvcm1zLmxlbmd0aFxuICAgICAgICAgIH0gaW4gcHJvZ3JhbSBcIiR7YXJ0aWZhY3QucHJvZ3JhbUluZm8ubmFtZX1cIi5gLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwcm9ncmFtVW5pZm9ybXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgdW5pZm9ybSA9IHByb2dyYW1Vbmlmb3Jtc1tpXTtcbiAgICAgICAgY29uc3QgYWN0dWFsVHlwZSA9IHVuaWZvcm0udHlwZTtcbiAgICAgICAgY29uc3QgYWN0dWFsTGVuZ3RoID0gdHlwZW9mIHVuaWZvcm0uZGF0YSA9PT0gJ251bWJlcicgPyAxIDogdW5pZm9ybS5kYXRhLmxlbmd0aDtcbiAgICAgICAgY29uc3QgW3R5cGUsIGxlbmd0aF0gPSBhcnRpZmFjdC51bmlmb3JtVmFyaWFibGVzSW5mb1tpXTtcbiAgICAgICAgaWYgKGFjdHVhbFR5cGUgIT09IHR5cGUgfHwgYWN0dWFsTGVuZ3RoICE9PSBsZW5ndGgpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgVW5pZm9ybSB2YXJpYWJsZSAke2l9IG1pc21hdGNoOiBleHBlY3QgdHlwZSAke3R5cGV9IHdpdGggc2l6ZSAke2xlbmd0aH0sIGdvdCB0eXBlICR7XG4gICAgICAgICAgICAgIGFjdHVhbFR5cGVcbiAgICAgICAgICAgIH0gd2l0aCBzaXplICR7YWN0dWFsTGVuZ3RofSBpbiBwcm9ncmFtIFwiJHthcnRpZmFjdC5wcm9ncmFtSW5mby5uYW1lfVwiLmAsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIExPR19ERUJVRyhcbiAgICAgICdpbmZvJyxcbiAgICAgICgpID0+XG4gICAgICAgIGBbUHJvZ3JhbU1hbmFnZXJdIHJ1biBcIiR7cHJvZ3JhbS5uYW1lfVwiIChrZXk9JHtrZXl9KSB3aXRoICR7bm9ybWFsaXplZERpc3BhdGNoR3JvdXBbMF19eCR7XG4gICAgICAgICAgbm9ybWFsaXplZERpc3BhdGNoR3JvdXBbMV1cbiAgICAgICAgfXgke25vcm1hbGl6ZWREaXNwYXRjaEdyb3VwWzJdfWAsXG4gICAgKTtcblxuICAgIGlmICh0aGlzLnF1ZXJ5VHlwZSAhPT0gJ25vbmUnIHx8IHRoaXMuc2Vzc2lvblN0YXR1cyA9PT0gJ2NhcHR1cmluZycpIHtcbiAgICAgIGNvbnN0IHBlbmRpbmdLZXJuZWxJbmZvOiBQZW5kaW5nS2VybmVsSW5mbyA9IHtcbiAgICAgICAga2VybmVsSWQ6IHRoaXMuY3VycmVudEtlcm5lbElkISxcbiAgICAgICAgcHJvZ3JhbU5hbWU6IGFydGlmYWN0LnByb2dyYW1JbmZvLm5hbWUsXG4gICAgICAgIGlucHV0VGVuc29yVmlld3MsXG4gICAgICAgIG91dHB1dFRlbnNvclZpZXdzLFxuICAgICAgfTtcbiAgICAgIHRoaXMucGVuZGluZ0tlcm5lbHMucHVzaChwZW5kaW5nS2VybmVsSW5mbyk7XG5cbiAgICAgIGlmICh0aGlzLnNlc3Npb25TdGF0dXMgPT09ICdjYXB0dXJpbmcnKSB7XG4gICAgICAgIGNvbnN0IHNlc3Npb25QZW5kaW5nS2VybmVscyA9IHRoaXMuY2FwdHVyZWRQZW5kaW5nS2VybmVscy5nZXQodGhpcy5jdXJyZW50U2Vzc2lvbklkISk7XG4gICAgICAgIHNlc3Npb25QZW5kaW5nS2VybmVscyEucHVzaChwZW5kaW5nS2VybmVsSW5mbyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5wcm9ncmFtTWFuYWdlci5ydW4oYXJ0aWZhY3QsIGlucHV0RGF0YXMsIG91dHB1dERhdGFzLCBub3JtYWxpemVkRGlzcGF0Y2hHcm91cCwgdW5pZm9ybUJ1ZmZlckJpbmRpbmcpO1xuXG4gICAgVFJBQ0VfRlVOQ19FTkQocHJvZ3JhbS5uYW1lKTtcbiAgICByZXR1cm4gb3V0cHV0VGVuc29yVmlld3M7XG4gIH1cblxuICB1cGxvYWQoZ3B1RGF0YUlkOiBudW1iZXIsIGRhdGE6IFVpbnQ4QXJyYXkpOiB2b2lkIHtcbiAgICB0aGlzLmdwdURhdGFNYW5hZ2VyLnVwbG9hZChncHVEYXRhSWQsIGRhdGEpO1xuICB9XG5cbiAgbWVtY3B5KHNyYzogbnVtYmVyLCBkc3Q6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIubWVtY3B5KHNyYywgZHN0KTtcbiAgfVxuXG4gIGFzeW5jIGRvd25sb2FkKGdwdURhdGFJZDogbnVtYmVyLCBnZXRUYXJnZXRCdWZmZXI6ICgpID0+IFVpbnQ4QXJyYXkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyB0aGUgdW5kZXJseWluZyBidWZmZXIgbWF5IGJlIGNoYW5nZWQgYWZ0ZXIgdGhlIGFzeW5jIGZ1bmN0aW9uIGlzIGNhbGxlZC4gc28gd2UgdXNlIGEgZ2V0dGVyIGZ1bmN0aW9uIHRvIG1ha2Ugc3VyZVxuICAgIC8vIHRoZSBidWZmZXIgaXMgdXAtdG8tZGF0ZS5cbiAgICBhd2FpdCB0aGlzLmdwdURhdGFNYW5hZ2VyLmRvd25sb2FkKGdwdURhdGFJZCwgZ2V0VGFyZ2V0QnVmZmVyKTtcbiAgfVxuXG4gIGFsbG9jKHNpemU6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuZ3B1RGF0YU1hbmFnZXIuY3JlYXRlKHNpemUpLmlkO1xuICB9XG5cbiAgZnJlZShwdHI6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuZ3B1RGF0YU1hbmFnZXIucmVsZWFzZShwdHIpO1xuICB9XG5cbiAgY3JlYXRlS2VybmVsKGtlcm5lbFR5cGU6IHN0cmluZywga2VybmVsSWQ6IG51bWJlciwgYXR0cmlidXRlOiB1bmtub3duLCBrZXJuZWxOYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBvcCA9IFdFQkdQVV9PUF9SRVNPTFZFX1JVTEVTLmdldChrZXJuZWxUeXBlKTtcbiAgICBpZiAoIW9wKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGtlcm5lbCBub3QgaW1wbGVtZW50ZWQ6ICR7a2VybmVsVHlwZX1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBrZXJuZWxJbmZvOiBLZXJuZWxJbmZvID0ge1xuICAgICAga2VybmVsVHlwZSxcbiAgICAgIGtlcm5lbE5hbWUsXG4gICAgICBrZXJuZWxFbnRyeTogb3BbMF0sXG4gICAgICBhdHRyaWJ1dGVzOiBbb3BbMV0sIGF0dHJpYnV0ZV0sXG4gICAgfTtcbiAgICB0aGlzLmtlcm5lbHMuc2V0KGtlcm5lbElkLCBrZXJuZWxJbmZvKTtcbiAgfVxuXG4gIHJlbGVhc2VLZXJuZWwoa2VybmVsSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHBlcnNpc3RlbnREYXRhID0gdGhpcy5rZXJuZWxQZXJzaXN0ZW50RGF0YS5nZXQoa2VybmVsSWQpO1xuICAgIGlmIChwZXJzaXN0ZW50RGF0YSkge1xuICAgICAgZm9yIChjb25zdCBkYXRhIG9mIHBlcnNpc3RlbnREYXRhKSB7XG4gICAgICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIucmVsZWFzZShkYXRhLmlkKTtcbiAgICAgIH1cbiAgICAgIHRoaXMua2VybmVsUGVyc2lzdGVudERhdGEuZGVsZXRlKGtlcm5lbElkKTtcbiAgICB9XG5cbiAgICB0aGlzLmtlcm5lbEN1c3RvbURhdGEuZGVsZXRlKGtlcm5lbElkKTtcbiAgICB0aGlzLmtlcm5lbHMuZGVsZXRlKGtlcm5lbElkKTtcbiAgfVxuXG4gIGNvbXB1dGVLZXJuZWwoa2VybmVsSWQ6IG51bWJlciwgY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGVycm9yczogQXJyYXk8UHJvbWlzZTxzdHJpbmcgfCBudWxsPj4pOiBudW1iZXIge1xuICAgIGNvbnN0IGtlcm5lbCA9IHRoaXMua2VybmVscy5nZXQoa2VybmVsSWQpO1xuICAgIGlmICgha2VybmVsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGtlcm5lbCBub3QgY3JlYXRlZDogJHtrZXJuZWxJZH1gKTtcbiAgICB9XG4gICAgY29uc3Qga2VybmVsVHlwZSA9IGtlcm5lbC5rZXJuZWxUeXBlO1xuICAgIGNvbnN0IGtlcm5lbE5hbWUgPSBrZXJuZWwua2VybmVsTmFtZTtcbiAgICBjb25zdCBrZXJuZWxFbnRyeSA9IGtlcm5lbC5rZXJuZWxFbnRyeTtcbiAgICBjb25zdCBhdHRyaWJ1dGVzID0ga2VybmVsLmF0dHJpYnV0ZXM7XG4gICAgaWYgKHRoaXMuY3VycmVudEtlcm5lbElkICE9PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGtlcm5lbCBcIlske2tlcm5lbFR5cGV9XSAke2tlcm5lbE5hbWV9XCIgaXMgbm90IGFsbG93ZWQgdG8gYmUgY2FsbGVkIHJlY3Vyc2l2ZWx5YCk7XG4gICAgfVxuICAgIHRoaXMuY3VycmVudEtlcm5lbElkID0ga2VybmVsSWQ7XG5cbiAgICAvLyBwYXJzZSBhdHRyaWJ1dGVzIGlmIG5lY2Vzc2FyeVxuICAgIGlmIChhdHRyaWJ1dGVzWzBdKSB7XG4gICAgICBhdHRyaWJ1dGVzWzFdID0gYXR0cmlidXRlc1swXShhdHRyaWJ1dGVzWzFdKTtcbiAgICAgIGF0dHJpYnV0ZXNbMF0gPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgTE9HX0RFQlVHKCdpbmZvJywgKCkgPT4gYFtXZWJHUFVdIFN0YXJ0IHRvIHJ1biBrZXJuZWwgXCJbJHtrZXJuZWxUeXBlfV0gJHtrZXJuZWxOYW1lfVwiLi4uYCk7XG5cbiAgICBjb25zdCB1c2VFcnJvclNjb3BlID0gdGhpcy5lbnYuZGVidWc7XG5cbiAgICB0aGlzLnRlbXBvcmFyeURhdGEgPSBbXTtcbiAgICB0cnkge1xuICAgICAgaWYgKHVzZUVycm9yU2NvcGUpIHtcbiAgICAgICAgdGhpcy5kZXZpY2UucHVzaEVycm9yU2NvcGUoJ3ZhbGlkYXRpb24nKTtcbiAgICAgIH1cblxuICAgICAga2VybmVsRW50cnkoY29udGV4dCwgYXR0cmlidXRlc1sxXSk7XG4gICAgICByZXR1cm4gMDsgLy8gT1JUX09LXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZXJyb3JzLnB1c2goUHJvbWlzZS5yZXNvbHZlKGBbV2ViR1BVXSBLZXJuZWwgXCJbJHtrZXJuZWxUeXBlfV0gJHtrZXJuZWxOYW1lfVwiIGZhaWxlZC4gJHtlfWApKTtcbiAgICAgIHJldHVybiAxOyAvLyBPUlRfRkFJTFxuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAodXNlRXJyb3JTY29wZSkge1xuICAgICAgICBlcnJvcnMucHVzaChcbiAgICAgICAgICB0aGlzLmRldmljZVxuICAgICAgICAgICAgLnBvcEVycm9yU2NvcGUoKVxuICAgICAgICAgICAgLnRoZW4oKGVycikgPT5cbiAgICAgICAgICAgICAgZXJyID8gYEdQVSB2YWxpZGF0aW9uIGVycm9yIGZvciBrZXJuZWwgXCJbJHtrZXJuZWxUeXBlfV0gJHtrZXJuZWxOYW1lfVwiOiAke2Vyci5tZXNzYWdlfWAgOiBudWxsLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgZm9yIChjb25zdCBkYXRhIG9mIHRoaXMudGVtcG9yYXJ5RGF0YSkge1xuICAgICAgICB0aGlzLmdwdURhdGFNYW5hZ2VyLnJlbGVhc2UoZGF0YS5pZCk7XG4gICAgICB9XG4gICAgICB0aGlzLnRlbXBvcmFyeURhdGEgPSBbXTtcbiAgICAgIHRoaXMuY3VycmVudEtlcm5lbElkID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvLyAjcmVnaW9uIGV4dGVybmFsIGJ1ZmZlclxuICByZWdpc3RlckJ1ZmZlcihzZXNzaW9uSWQ6IG51bWJlciwgaW5kZXg6IG51bWJlciwgYnVmZmVyOiBHUFVCdWZmZXIsIHNpemU6IG51bWJlcik6IG51bWJlciB7XG4gICAgbGV0IHNlc3Npb25JbnB1dE91dHB1dE1hcHBpbmcgPSB0aGlzLnNlc3Npb25FeHRlcm5hbERhdGFNYXBwaW5nLmdldChzZXNzaW9uSWQpO1xuICAgIGlmICghc2Vzc2lvbklucHV0T3V0cHV0TWFwcGluZykge1xuICAgICAgc2Vzc2lvbklucHV0T3V0cHV0TWFwcGluZyA9IG5ldyBNYXAoKTtcbiAgICAgIHRoaXMuc2Vzc2lvbkV4dGVybmFsRGF0YU1hcHBpbmcuc2V0KHNlc3Npb25JZCwgc2Vzc2lvbklucHV0T3V0cHV0TWFwcGluZyk7XG4gICAgfVxuXG4gICAgLy8gdGhlIGJ1ZmZlciBtYXkgYmUgdXNlciBjcmVhdGVkLCBvciBtYW5hZ2VkIGJ5IEdQVSBkYXRhIG1hbmFnZXIuXG4gICAgLy8gVGhlIEdQVSBkYXRhIG1hbmFnZXIgd2lsbCBub3QgbWFuYWdlIHRoZXNlIGJ1ZmZlcnMuIHdlIHJlZ2lzdGVyIHRoZW0gYXMgZXh0ZXJuYWwgYnVmZmVycy5cbiAgICAvL1xuICAgIC8vIFRoZSBtYXAgYHNlc3Npb25JbnB1dE91dHB1dE1hcHBpbmdgIGlzIHVzZWQgdG8gc3RvcmUgdGhlIGRhdGEgSUQgYW5kIGJ1ZmZlciBmb3IgZWFjaCBpbnB1dC9vdXRwdXQuIE9uY2UgYVxuICAgIC8vIHNwZWNpZmljIGlucHV0L291dHB1dCBpcyByZWdpc3RlcmVkLCB0aGUgZGF0YSBJRCB3aWxsIG5vdCBjaGFuZ2UuXG4gICAgY29uc3QgcHJldmlvdXNCdWZmZXIgPSBzZXNzaW9uSW5wdXRPdXRwdXRNYXBwaW5nLmdldChpbmRleCk7XG4gICAgY29uc3QgaWQgPSB0aGlzLmdwdURhdGFNYW5hZ2VyLnJlZ2lzdGVyRXh0ZXJuYWxCdWZmZXIoYnVmZmVyLCBzaXplLCBwcmV2aW91c0J1ZmZlcik7XG4gICAgc2Vzc2lvbklucHV0T3V0cHV0TWFwcGluZy5zZXQoaW5kZXgsIFtpZCwgYnVmZmVyXSk7XG4gICAgcmV0dXJuIGlkO1xuICB9XG4gIHVucmVnaXN0ZXJCdWZmZXJzKHNlc3Npb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgc2Vzc2lvbklucHV0T3V0cHV0TWFwcGluZyA9IHRoaXMuc2Vzc2lvbkV4dGVybmFsRGF0YU1hcHBpbmcuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKHNlc3Npb25JbnB1dE91dHB1dE1hcHBpbmcpIHtcbiAgICAgIHNlc3Npb25JbnB1dE91dHB1dE1hcHBpbmcuZm9yRWFjaCgoYnVmZmVySW5mbykgPT4gdGhpcy5ncHVEYXRhTWFuYWdlci51bnJlZ2lzdGVyRXh0ZXJuYWxCdWZmZXIoYnVmZmVySW5mb1swXSkpO1xuICAgICAgdGhpcy5zZXNzaW9uRXh0ZXJuYWxEYXRhTWFwcGluZy5kZWxldGUoc2Vzc2lvbklkKTtcbiAgICB9XG4gIH1cbiAgZ2V0QnVmZmVyKGdwdURhdGFJZDogbnVtYmVyKTogR1BVQnVmZmVyIHtcbiAgICBjb25zdCBncHVEYXRhID0gdGhpcy5ncHVEYXRhTWFuYWdlci5nZXQoZ3B1RGF0YUlkKTtcbiAgICBpZiAoIWdwdURhdGEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgbm8gR1BVIGRhdGEgZm9yIGJ1ZmZlcjogJHtncHVEYXRhSWR9YCk7XG4gICAgfVxuICAgIHJldHVybiBncHVEYXRhLmJ1ZmZlcjtcbiAgfVxuICBjcmVhdGVEb3dubG9hZGVyKFxuICAgIGdwdUJ1ZmZlcjogR1BVQnVmZmVyLFxuICAgIHNpemU6IG51bWJlcixcbiAgICB0eXBlOiBUZW5zb3IuR3B1QnVmZmVyRGF0YVR5cGVzLFxuICApOiAoKSA9PiBQcm9taXNlPFRlbnNvci5EYXRhVHlwZT4ge1xuICAgIHJldHVybiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZG93bmxvYWRHcHVEYXRhKHRoaXMsIGdwdUJ1ZmZlciwgc2l6ZSk7XG4gICAgICByZXR1cm4gY3JlYXRlVmlldyhkYXRhLmJ1ZmZlciwgdHlwZSk7XG4gICAgfTtcbiAgfVxuICAvLyAjZW5kcmVnaW9uXG4gIHdyaXRlVGltZXN0YW1wKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5xdWVyeVR5cGUgIT09ICdpbnNpZGUtcGFzc2VzJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgKHRoaXMuY29tcHV0ZVBhc3NFbmNvZGVyIGFzIGFueSkud3JpdGVUaW1lc3RhbXAodGhpcy5xdWVyeVNldCwgaW5kZXgpO1xuICB9XG4gIHNldFF1ZXJ5VHlwZSgpOiB2b2lkIHtcbiAgICB0aGlzLnF1ZXJ5VHlwZSA9ICdub25lJztcbiAgICBpZiAoXG4gICAgICB0aGlzLmVudi53ZWJncHUucHJvZmlsaW5nPy5tb2RlID09PSAnZGVmYXVsdCcgfHxcbiAgICAgICh0eXBlb2YgdGhpcy5lbnYudHJhY2UgPT09ICd1bmRlZmluZWQnID8gdGhpcy5lbnYud2FzbS50cmFjZSA6IHRoaXMuZW52LnRyYWNlKVxuICAgICkge1xuICAgICAgaWYgKHRoaXMuZGV2aWNlLmZlYXR1cmVzLmhhcygnY2hyb21pdW0tZXhwZXJpbWVudGFsLXRpbWVzdGFtcC1xdWVyeS1pbnNpZGUtcGFzc2VzJykpIHtcbiAgICAgICAgdGhpcy5xdWVyeVR5cGUgPSAnaW5zaWRlLXBhc3Nlcyc7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuZGV2aWNlLmZlYXR1cmVzLmhhcygndGltZXN0YW1wLXF1ZXJ5JykpIHtcbiAgICAgICAgdGhpcy5xdWVyeVR5cGUgPSAnYXQtcGFzc2VzJztcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMucXVlcnlUeXBlICE9PSAnbm9uZScgJiYgdHlwZW9mIHRoaXMucXVlcnlTZXQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHRoaXMucXVlcnlTZXQgPSB0aGlzLmRldmljZS5jcmVhdGVRdWVyeVNldCh7XG4gICAgICAgICAgdHlwZTogJ3RpbWVzdGFtcCcsXG4gICAgICAgICAgY291bnQ6IHRoaXMubWF4RGlzcGF0Y2hOdW1iZXIgKiAyLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5xdWVyeVJlc29sdmVCdWZmZXIgPSB0aGlzLmRldmljZS5jcmVhdGVCdWZmZXIoXG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICAgICAgICB7IHNpemU6IHRoaXMubWF4RGlzcGF0Y2hOdW1iZXIgKiAyICogOCwgdXNhZ2U6IEdQVUJ1ZmZlclVzYWdlLkNPUFlfU1JDIHwgR1BVQnVmZmVyVXNhZ2UuUVVFUllfUkVTT0xWRSB9LFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNhcHR1cmVCZWdpbigpOiB2b2lkIHtcbiAgICBMT0dfREVCVUcoJ2luZm8nLCAnY2FwdHVyZUJlZ2luJyk7XG4gICAgaWYgKCF0aGlzLmNhcHR1cmVkQ29tbWFuZExpc3QuZ2V0KHRoaXMuY3VycmVudFNlc3Npb25JZCEpKSB7XG4gICAgICB0aGlzLmNhcHR1cmVkQ29tbWFuZExpc3Quc2V0KHRoaXMuY3VycmVudFNlc3Npb25JZCEsIFtdKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLmNhcHR1cmVkUGVuZGluZ0tlcm5lbHMuZ2V0KHRoaXMuY3VycmVudFNlc3Npb25JZCEpKSB7XG4gICAgICB0aGlzLmNhcHR1cmVkUGVuZGluZ0tlcm5lbHMuc2V0KHRoaXMuY3VycmVudFNlc3Npb25JZCEsIFtdKTtcbiAgICB9XG4gICAgLy8gZmx1c2ggdGhlIGxlZnQgY29tbWFuZHMgYmVmb3JlIHdlIGNoYW5nZSB0aGUgc3RhdHVzLlxuICAgIHRoaXMuZmx1c2goKTtcbiAgICB0aGlzLnNlc3Npb25TdGF0dXMgPSAnY2FwdHVyaW5nJztcbiAgfVxuICBjYXB0dXJlRW5kKCk6IHZvaWQge1xuICAgIExPR19ERUJVRygnaW5mbycsICdjYXB0dXJlRW5kJyk7XG4gICAgLy8gZmx1c2ggdGhlIGxlZnQgY29tbWFuZHMgYmVmb3JlIHdlIGNoYW5nZSB0aGUgc3RhdHVzLlxuICAgIHRoaXMuZmx1c2goKTtcbiAgICB0aGlzLnNlc3Npb25TdGF0dXMgPSAnZGVmYXVsdCc7XG4gIH1cbiAgcmVwbGF5KCk6IHZvaWQge1xuICAgIExPR19ERUJVRygnaW5mbycsICdyZXBsYXknKTtcbiAgICB0aGlzLnNlc3Npb25TdGF0dXMgPSAncmVwbGF5aW5nJztcbiAgICBjb25zdCBzZXNzaW9uQ29tbWFuZExpc3QgPSB0aGlzLmNhcHR1cmVkQ29tbWFuZExpc3QuZ2V0KHRoaXMuY3VycmVudFNlc3Npb25JZCEpO1xuICAgIGNvbnN0IHNlc3Npb25QZW5kaW5nS2VybmVscyA9IHRoaXMuY2FwdHVyZWRQZW5kaW5nS2VybmVscy5nZXQodGhpcy5jdXJyZW50U2Vzc2lvbklkISk7XG4gICAgY29uc3QgbGVuZ3RoID0gc2Vzc2lvbkNvbW1hbmRMaXN0IS5sZW5ndGg7XG4gICAgdGhpcy5wZW5kaW5nS2VybmVscyA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGNvbXB1dGVQYXNzRW5jb2RlciA9IHRoaXMuZ2V0Q29tcHV0ZVBhc3NFbmNvZGVyKCk7XG4gICAgICBjb25zdCBjb21tYW5kID0gc2Vzc2lvbkNvbW1hbmRMaXN0IVtpXTtcbiAgICAgIHRoaXMud3JpdGVUaW1lc3RhbXAodGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgKiAyKTtcbiAgICAgIGNvbXB1dGVQYXNzRW5jb2Rlci5zZXRQaXBlbGluZShjb21tYW5kLmNvbXB1dGVQaXBlbGluZSk7XG4gICAgICBjb21wdXRlUGFzc0VuY29kZXIuc2V0QmluZEdyb3VwKDAsIGNvbW1hbmQuYmluZEdyb3VwKTtcbiAgICAgIGNvbXB1dGVQYXNzRW5jb2Rlci5kaXNwYXRjaFdvcmtncm91cHMoLi4uY29tbWFuZC5kaXNwYXRjaEdyb3VwKTtcbiAgICAgIHRoaXMud3JpdGVUaW1lc3RhbXAodGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgKiAyICsgMSk7XG4gICAgICB0aGlzLnBlbmRpbmdEaXNwYXRjaE51bWJlcisrO1xuICAgICAgaWYgKHRoaXMucXVlcnlUeXBlICE9PSAnbm9uZScpIHtcbiAgICAgICAgdGhpcy5wZW5kaW5nS2VybmVscy5wdXNoKHNlc3Npb25QZW5kaW5nS2VybmVscyFbaV0pO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMucGVuZGluZ0Rpc3BhdGNoTnVtYmVyID49IHRoaXMubWF4RGlzcGF0Y2hOdW1iZXIgfHwgdGhpcy5xdWVyeVR5cGUgPT09ICdhdC1wYXNzZXMnKSB7XG4gICAgICAgIHRoaXMuZW5kQ29tcHV0ZVBhc3MoKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLnBlbmRpbmdEaXNwYXRjaE51bWJlciA+PSB0aGlzLm1heERpc3BhdGNoTnVtYmVyKSB7XG4gICAgICAgIHRoaXMuZmx1c2goKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gZmx1c2ggdGhlIGxlZnQgY29tbWFuZHMgYmVmb3JlIHdlIGNoYW5nZSB0aGUgc3RhdHVzLlxuICAgIHRoaXMuZmx1c2goKTtcbiAgICB0aGlzLnNlc3Npb25TdGF0dXMgPSAnZGVmYXVsdCc7XG4gIH1cblxuICBvbkNyZWF0ZVNlc3Npb24oKTogdm9pZCB7XG4gICAgdGhpcy5ncHVEYXRhTWFuYWdlci5vbkNyZWF0ZVNlc3Npb24oKTtcbiAgfVxuXG4gIG9uUmVsZWFzZVNlc3Npb24oc2Vzc2lvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnVucmVnaXN0ZXJCdWZmZXJzKHNlc3Npb25JZCk7XG4gICAgaWYgKHRoaXMuY2FwdHVyZWRDb21tYW5kTGlzdC5oYXMoc2Vzc2lvbklkKSkge1xuICAgICAgdGhpcy5jYXB0dXJlZENvbW1hbmRMaXN0LmRlbGV0ZShzZXNzaW9uSWQpO1xuICAgIH1cbiAgICBpZiAodGhpcy5jYXB0dXJlZFBlbmRpbmdLZXJuZWxzLmhhcyhzZXNzaW9uSWQpKSB7XG4gICAgICB0aGlzLmNhcHR1cmVkUGVuZGluZ0tlcm5lbHMuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgfVxuICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIub25SZWxlYXNlU2Vzc2lvbihzZXNzaW9uSWQpO1xuICB9XG5cbiAgb25SdW5TdGFydChzZXNzaW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudFNlc3Npb25JZCA9IHNlc3Npb25JZDtcbiAgICB0aGlzLnNldFF1ZXJ5VHlwZSgpO1xuICB9XG59XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB0eXBlIHsgRW52IH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHsgY2FsY3VsYXRlVGVuc29yU2l6ZUluQnl0ZXMsIERhdGFUeXBlIH0gZnJvbSAnLi4vd2FzbS1jb21tb24nO1xuXG5pbXBvcnQgdHlwZSB7IE9ydFdhc21Nb2R1bGUgfSBmcm9tICcuLi93YXNtLXR5cGVzJztcblxuaW1wb3J0IHR5cGUgeyBXZWJHcHVCYWNrZW5kIH0gZnJvbSAnLi9iYWNrZW5kLXdlYmdwdSc7XG5pbXBvcnQgeyBMT0dfREVCVUcgfSBmcm9tICcuL2xvZyc7XG5pbXBvcnQgdHlwZSB7IFRlbnNvclZpZXcgfSBmcm9tICcuL3RlbnNvci12aWV3JztcbmltcG9ydCB7IFNoYXBlVXRpbCB9IGZyb20gJy4vdXRpbCc7XG5pbXBvcnQgdHlwZSB7IEFkYXB0ZXJJbmZvLCBDb21wdXRlQ29udGV4dCwgQ29tcHV0ZUNvbnRleHRJbnB1dHNPdXRwdXRzTWFwcGluZywgUHJvZ3JhbUluZm8gfSBmcm9tICcuL3dlYmdwdS90eXBlcyc7XG5pbXBvcnQgeyBXZWJOTkJhY2tlbmQgfSBmcm9tICcuL2JhY2tlbmQtd2Vibm4nO1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1iaXR3aXNlICovXG5cbmNsYXNzIFRlbnNvclZpZXdJbXBsIGltcGxlbWVudHMgVGVuc29yVmlldyB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgbW9kdWxlOiBPcnRXYXNtTW9kdWxlLFxuICAgIHB1YmxpYyByZWFkb25seSBkYXRhVHlwZTogbnVtYmVyLFxuICAgIHB1YmxpYyByZWFkb25seSBkYXRhOiBudW1iZXIsXG4gICAgcHVibGljIHJlYWRvbmx5IGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICApIHt9XG5cbiAgZ2V0RmxvYXQzMkFycmF5KCk6IEZsb2F0MzJBcnJheSB7XG4gICAgaWYgKHRoaXMuZGF0YVR5cGUgIT09IERhdGFUeXBlLmZsb2F0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZGF0YSB0eXBlJyk7XG4gICAgfVxuICAgIGNvbnN0IGVsZW1lbnRDb3VudCA9IFNoYXBlVXRpbC5zaXplKHRoaXMuZGltcyk7XG4gICAgcmV0dXJuIGVsZW1lbnRDb3VudCA9PT0gMFxuICAgICAgPyBuZXcgRmxvYXQzMkFycmF5KClcbiAgICAgIDogbmV3IEZsb2F0MzJBcnJheSh0aGlzLm1vZHVsZS5IRUFQOC5idWZmZXIsIHRoaXMuZGF0YSwgZWxlbWVudENvdW50KTtcbiAgfVxuXG4gIGdldEJpZ0ludDY0QXJyYXkoKTogQmlnSW50NjRBcnJheSB7XG4gICAgaWYgKHRoaXMuZGF0YVR5cGUgIT09IERhdGFUeXBlLmludDY0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZGF0YSB0eXBlJyk7XG4gICAgfVxuICAgIGNvbnN0IGVsZW1lbnRDb3VudCA9IFNoYXBlVXRpbC5zaXplKHRoaXMuZGltcyk7XG4gICAgcmV0dXJuIGVsZW1lbnRDb3VudCA9PT0gMFxuICAgICAgPyBuZXcgQmlnSW50NjRBcnJheSgpXG4gICAgICA6IG5ldyBCaWdJbnQ2NEFycmF5KHRoaXMubW9kdWxlLkhFQVA4LmJ1ZmZlciwgdGhpcy5kYXRhLCBlbGVtZW50Q291bnQpO1xuICB9XG5cbiAgZ2V0SW50MzJBcnJheSgpOiBJbnQzMkFycmF5IHtcbiAgICBpZiAodGhpcy5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuaW50MzIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBkYXRhIHR5cGUnKTtcbiAgICB9XG4gICAgY29uc3QgZWxlbWVudENvdW50ID0gU2hhcGVVdGlsLnNpemUodGhpcy5kaW1zKTtcbiAgICByZXR1cm4gZWxlbWVudENvdW50ID09PSAwID8gbmV3IEludDMyQXJyYXkoKSA6IG5ldyBJbnQzMkFycmF5KHRoaXMubW9kdWxlLkhFQVA4LmJ1ZmZlciwgdGhpcy5kYXRhLCBlbGVtZW50Q291bnQpO1xuICB9XG5cbiAgZ2V0VWludDE2QXJyYXkoKTogVWludDE2QXJyYXkge1xuICAgIGlmICh0aGlzLmRhdGFUeXBlICE9PSBEYXRhVHlwZS5mbG9hdDE2ICYmIHRoaXMuZGF0YVR5cGUgIT09IERhdGFUeXBlLnVpbnQxNikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGRhdGEgdHlwZScpO1xuICAgIH1cbiAgICBjb25zdCBlbGVtZW50Q291bnQgPSBTaGFwZVV0aWwuc2l6ZSh0aGlzLmRpbXMpO1xuICAgIHJldHVybiBlbGVtZW50Q291bnQgPT09IDAgPyBuZXcgVWludDE2QXJyYXkoKSA6IG5ldyBVaW50MTZBcnJheSh0aGlzLm1vZHVsZS5IRUFQOC5idWZmZXIsIHRoaXMuZGF0YSwgZWxlbWVudENvdW50KTtcbiAgfVxuXG4gIHJlc2hhcGUobmV3RGltczogcmVhZG9ubHkgbnVtYmVyW10pOiBUZW5zb3JWaWV3IHtcbiAgICBpZiAoU2hhcGVVdGlsLnNpemUobmV3RGltcykgIT09IFNoYXBlVXRpbC5zaXplKHRoaXMuZGltcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBuZXcgc2hhcGUnKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBUZW5zb3JWaWV3SW1wbCh0aGlzLm1vZHVsZSwgdGhpcy5kYXRhVHlwZSwgdGhpcy5kYXRhLCBuZXdEaW1zKTtcbiAgfVxufVxuXG5jbGFzcyBDb21wdXRlQ29udGV4dEltcGwgaW1wbGVtZW50cyBDb21wdXRlQ29udGV4dCB7XG4gIHJlYWRvbmx5IGFkYXB0ZXJJbmZvOiBBZGFwdGVySW5mbztcbiAgcmVhZG9ubHkgb3BLZXJuZWxDb250ZXh0OiBudW1iZXI7XG4gIHJlYWRvbmx5IGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdO1xuICByZWFkb25seSBvdXRwdXRDb3VudDogbnVtYmVyO1xuICBnZXQga2VybmVsQ3VzdG9tRGF0YSgpOiB7IFtrZXk6IHN0cmluZ106IHVua25vd24gfSB7XG4gICAgcmV0dXJuIHRoaXMuYmFja2VuZC5jdXJyZW50S2VybmVsQ3VzdG9tRGF0YTtcbiAgfVxuICBnZXQgY3VzdG9tRGF0YUJ1ZmZlcigpOiBVaW50OEFycmF5IHtcbiAgICByZXR1cm4gdGhpcy5tb2R1bGUuSEVBUFU4LnN1YmFycmF5KHRoaXMuY3VzdG9tRGF0YU9mZnNldCwgdGhpcy5jdXN0b21EYXRhT2Zmc2V0ICsgdGhpcy5jdXN0b21EYXRhU2l6ZSk7XG4gIH1cbiAgcHJpdmF0ZSBjdXN0b21EYXRhT2Zmc2V0ID0gMDtcbiAgcHJpdmF0ZSBjdXN0b21EYXRhU2l6ZSA9IDA7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgbW9kdWxlOiBPcnRXYXNtTW9kdWxlLFxuICAgIHByaXZhdGUgYmFja2VuZDogV2ViR3B1QmFja2VuZCxcbiAgICBjb250ZXh0RGF0YU9mZnNldDogbnVtYmVyLFxuICApIHtcbiAgICB0aGlzLmFkYXB0ZXJJbmZvID0gYmFja2VuZC5hZGFwdGVySW5mbztcblxuICAgIC8vIGV4dHJhY3QgY29udGV4dCBkYXRhXG4gICAgY29uc3QgcHRyU2l6ZSA9IG1vZHVsZS5QVFJfU0laRTtcbiAgICBsZXQgZGF0YUluZGV4ID0gY29udGV4dERhdGFPZmZzZXQgLyBtb2R1bGUuUFRSX1NJWkU7XG4gICAgY29uc3QgdHlwZSA9IHB0clNpemUgPT09IDQgPyAnaTMyJyA6ICdpNjQnO1xuICAgIHRoaXMub3BLZXJuZWxDb250ZXh0ID0gTnVtYmVyKG1vZHVsZS5nZXRWYWx1ZShwdHJTaXplICogZGF0YUluZGV4KyssIHR5cGUpKTtcbiAgICBjb25zdCBpbnB1dENvdW50ID0gTnVtYmVyKG1vZHVsZS5nZXRWYWx1ZShwdHJTaXplICogZGF0YUluZGV4KyssIHR5cGUpKTtcbiAgICB0aGlzLm91dHB1dENvdW50ID0gTnVtYmVyKG1vZHVsZS5nZXRWYWx1ZShwdHJTaXplICogZGF0YUluZGV4KyssIHR5cGUpKTtcbiAgICB0aGlzLmN1c3RvbURhdGFPZmZzZXQgPSBOdW1iZXIobW9kdWxlLmdldFZhbHVlKHB0clNpemUgKiBkYXRhSW5kZXgrKywgJyonKSk7XG4gICAgdGhpcy5jdXN0b21EYXRhU2l6ZSA9IE51bWJlcihtb2R1bGUuZ2V0VmFsdWUocHRyU2l6ZSAqIGRhdGFJbmRleCsrLCB0eXBlKSk7XG5cbiAgICBjb25zdCBpbnB1dHM6IFRlbnNvclZpZXdbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRDb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCBkYXRhVHlwZSA9IE51bWJlcihtb2R1bGUuZ2V0VmFsdWUocHRyU2l6ZSAqIGRhdGFJbmRleCsrLCB0eXBlKSk7XG4gICAgICBjb25zdCBkYXRhID0gTnVtYmVyKG1vZHVsZS5nZXRWYWx1ZShwdHJTaXplICogZGF0YUluZGV4KyssICcqJykpO1xuICAgICAgY29uc3QgZGltID0gTnVtYmVyKG1vZHVsZS5nZXRWYWx1ZShwdHJTaXplICogZGF0YUluZGV4KyssIHR5cGUpKTtcbiAgICAgIGNvbnN0IGRpbXM6IG51bWJlcltdID0gW107XG4gICAgICBmb3IgKGxldCBkID0gMDsgZCA8IGRpbTsgZCsrKSB7XG4gICAgICAgIGRpbXMucHVzaChOdW1iZXIobW9kdWxlLmdldFZhbHVlKHB0clNpemUgKiBkYXRhSW5kZXgrKywgdHlwZSkpKTtcbiAgICAgIH1cbiAgICAgIGlucHV0cy5wdXNoKG5ldyBUZW5zb3JWaWV3SW1wbChtb2R1bGUsIGRhdGFUeXBlLCBkYXRhLCBkaW1zKSk7XG4gICAgfVxuICAgIHRoaXMuaW5wdXRzID0gaW5wdXRzO1xuICB9XG5cbiAgY29tcHV0ZShwcm9ncmFtOiBQcm9ncmFtSW5mbywgaW5wdXRzT3V0cHV0c01hcHBpbmc/OiBDb21wdXRlQ29udGV4dElucHV0c091dHB1dHNNYXBwaW5nKTogVGVuc29yVmlld1tdIHtcbiAgICAvLyBwcmVwYXJlIGlucHV0cy4gaW5wdXRzIHNob3VsZCBhbHdheXMgYmUgdmFsaWQgZGF0YS5cbiAgICBjb25zdCBtYXBwZWRJbnB1dHMgPVxuICAgICAgaW5wdXRzT3V0cHV0c01hcHBpbmc/LmlucHV0cz8ubWFwKChpKSA9PiAodHlwZW9mIGkgPT09ICdudW1iZXInID8gdGhpcy5pbnB1dHNbaV0gOiBpKSkgPz8gdGhpcy5pbnB1dHM7XG4gICAgLy8gcHJlcGFyZSBvdXRwdXRzLlxuICAgIGNvbnN0IG91dHB1dEluZGljZXMgPSBpbnB1dHNPdXRwdXRzTWFwcGluZz8ub3V0cHV0cyA/PyBbXTtcbiAgICBjb25zdCBjcmVhdGVLZXJuZWxPdXRwdXQgPSAoaW5kZXg6IG51bWJlciwgZGF0YVR5cGU6IG51bWJlciwgZGltczogcmVhZG9ubHkgbnVtYmVyW10pOiBUZW5zb3JWaWV3ID0+XG4gICAgICBuZXcgVGVuc29yVmlld0ltcGwodGhpcy5tb2R1bGUsIGRhdGFUeXBlLCB0aGlzLm91dHB1dChpbmRleCwgZGltcyksIGRpbXMpO1xuICAgIGNvbnN0IGNyZWF0ZVRlbXBvcmFyeU91dHB1dCA9IChkYXRhVHlwZTogbnVtYmVyLCBkaW1zOiByZWFkb25seSBudW1iZXJbXSk6IFRlbnNvclZpZXcgPT4ge1xuICAgICAgY29uc3QgYnVmZmVyU2l6ZSA9IGNhbGN1bGF0ZVRlbnNvclNpemVJbkJ5dGVzKGRhdGFUeXBlLCBkaW1zKTtcbiAgICAgIGlmICghYnVmZmVyU2l6ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGRhdGEgdHlwZTogJHtkYXRhVHlwZX1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGdwdURhdGFJZCA9IGJ1ZmZlclNpemUgPiAwID8gdGhpcy5iYWNrZW5kLmdwdURhdGFNYW5hZ2VyLmNyZWF0ZShidWZmZXJTaXplKS5pZCA6IDA7XG4gICAgICByZXR1cm4gbmV3IFRlbnNvclZpZXdJbXBsKHRoaXMubW9kdWxlLCBkYXRhVHlwZSwgZ3B1RGF0YUlkLCBkaW1zKTtcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLmJhY2tlbmQucnVuKFxuICAgICAgcHJvZ3JhbSxcbiAgICAgIG1hcHBlZElucHV0cyxcbiAgICAgIG91dHB1dEluZGljZXMsXG4gICAgICBjcmVhdGVLZXJuZWxPdXRwdXQsXG4gICAgICBjcmVhdGVUZW1wb3JhcnlPdXRwdXQsXG4gICAgICB0aGlzLm91dHB1dENvdW50LFxuICAgICk7XG4gIH1cblxuICBvdXRwdXQoaW5kZXg6IG51bWJlciwgZGltczogcmVhZG9ubHkgbnVtYmVyW10pOiBudW1iZXIge1xuICAgIGNvbnN0IHN0YWNrID0gdGhpcy5tb2R1bGUuc3RhY2tTYXZlKCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHB0clNpemUgPSB0aGlzLm1vZHVsZS5QVFJfU0laRTtcbiAgICAgIGNvbnN0IHR5cGUgPSBwdHJTaXplID09PSA0ID8gJ2kzMicgOiAnaTY0JztcbiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLm1vZHVsZS5zdGFja0FsbG9jKCgxICsgZGltcy5sZW5ndGgpICogcHRyU2l6ZSAvKiBzaXplb2Yoc2l6ZV90KSAqLyk7XG4gICAgICB0aGlzLm1vZHVsZS5zZXRWYWx1ZShkYXRhLCBkaW1zLmxlbmd0aCwgdHlwZSk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRpbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy5tb2R1bGUuc2V0VmFsdWUoZGF0YSArIHB0clNpemUgKiAoaSArIDEpLCBkaW1zW2ldLCB0eXBlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLm1vZHVsZS5fSnNlcE91dHB1dCEodGhpcy5vcEtlcm5lbENvbnRleHQsIGluZGV4LCBkYXRhKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gZ2VuZXJhdGUga2VybmVsJ3Mgb3V0cHV0WyR7aW5kZXh9XSB3aXRoIGRpbXMgWyR7ZGltc31dLiBgICtcbiAgICAgICAgICAnSWYgeW91IGFyZSBydW5uaW5nIHdpdGggcHJlLWFsbG9jYXRlZCBvdXRwdXQsIHBsZWFzZSBtYWtlIHN1cmUgdGhlIG91dHB1dCB0eXBlL2RpbXMgYXJlIGNvcnJlY3QuICcgK1xuICAgICAgICAgIGBFcnJvcjogJHtlfWAsXG4gICAgICApO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLm1vZHVsZS5zdGFja1Jlc3RvcmUoc3RhY2spO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEluaXRpYWxpemUgSlNFUCB3aXRoIFdlYkdQVSBiYWNrZW5kLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgYWZ0ZXIgdGhlIFdlYkFzc2VtYmx5IG1vZHVsZSBpcyBsb2FkZWQgYW5kIGluaXRpYWxpemVkIChcIl9PcnRJbml0XCIgaXMgY2FsbGVkKSwgb25jZSBmb3JcbiAqIGVhY2ggb2YgdGhlIGZvbGxvd2luZyBFUHMgaWYgdGhleSBhcmUgc3BlY2lmaWVkOlxuICogLSBcIndlYmdwdVwiXG4gKiAtIFwid2Vibm5cIlxuICpcbiAqIEZvciBXZWJHUFUsIHRoaXMgZnVuY3Rpb24gZXhwZWN0czpcbiAqICAtIFdlYkdQVSBpcyBlbmFibGVkIGluIGJ1aWxkIChCVUlMRF9ERUZTLkRJU0FCTEVfSlNFUCA9PT0gZmFsc2UpLlxuICogIC0gV2ViR1BVIGlzIGF2YWlsYWJsZSBpbiBjdXJyZW50IGVudmlyb25tZW50LiAoYSB2YWxpZCBHUFVBZGFwdGVyIGlzIHBhc3NlZCBpbilcbiAqXG4gKiBGb3IgV2ViTk4sIHRoaXMgZnVuY3Rpb24gZXhwZWN0czpcbiAqIC0gV2ViTk4gaXMgZW5hYmxlZCBpbiBidWlsZCAoQlVJTERfREVGUy5ESVNBQkxFX0pTRVAgPT09IGZhbHNlKS5cbiAqIC0gV2ViTk4gaXMgYXZhaWxhYmxlIGluIGN1cnJlbnQgZW52aXJvbm1lbnQuIChuYXZpZ2F0b3IubWwgaXMgbm90IHVuZGVmaW5lZClcbiAqXG4gKiBJZiB0aGUgV2ViQXNzZW1ibHkgbW9kdWxlIGlzIG5vdCBidWlsdCB3aXRoIEpTRVAgc3VwcG9ydCwgdGhpcyBmdW5jdGlvbiB3aWxsIHRocm93IGFuIGVycm9yLiBUaGlzIHdpbGwgaW52YWxpZGF0ZVxuICogJ3dlYmdwdScvJ3dlYm5uJyBiYWNrZW5kLlxuICpcbiAqIEBwYXJhbSBuYW1lIC0gdGhlIG5hbWUgb2YgdGhlIEVQLCBlaXRoZXIgXCJ3ZWJncHVcIiBvciBcIndlYm5uXCJcbiAqIEBwYXJhbSBtb2R1bGUgLSB0aGUgT1JUIFdlYkFzc2VtYmx5IG1vZHVsZVxuICogQHBhcmFtIGVudiAtIHRoZSBPUlQgZW52aXJvbm1lbnQgdmFyaWFibGUgKG9ydC5lbnYpXG4gKiBAcGFyYW0gZ3B1QWRhcHRlciAtIHRoZSBwcmUtY3JlYXRlZCBHUFUgYWRhcHRlclxuICovXG5leHBvcnQgY29uc3QgaW5pdCA9IGFzeW5jIChcbiAgbmFtZTogJ3dlYmdwdScgfCAnd2Vibm4nLFxuICBtb2R1bGU6IE9ydFdhc21Nb2R1bGUsXG4gIGVudjogRW52LFxuICBncHVBZGFwdGVyPzogR1BVQWRhcHRlcixcbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBjb25zdCBqc2VwSW5pdCA9IG1vZHVsZS5qc2VwSW5pdDtcbiAgaWYgKCFqc2VwSW5pdCkge1xuICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGluaXRpYWxpemUgSlNFUC4gVGhlIFdlYkFzc2VtYmx5IG1vZHVsZSBpcyBub3QgYnVpbHQgd2l0aCBKU0VQIHN1cHBvcnQuJyk7XG4gIH1cblxuICBpZiAobmFtZSA9PT0gJ3dlYmdwdScpIHtcbiAgICBpZiAoIUJVSUxEX0RFRlMuVVNFX1dFQkdQVV9FUCkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMsIEB0eXBlc2NyaXB0LWVzbGludC9uby12YXItcmVxdWlyZXNcbiAgICAgIGNvbnN0IHdlYkdwdUJhY2tlbmRJbXBsID0gcmVxdWlyZSgnLi9iYWNrZW5kLXdlYmdwdScpLldlYkdwdUJhY2tlbmQ7XG4gICAgICBjb25zdCBiYWNrZW5kID0gbmV3IHdlYkdwdUJhY2tlbmRJbXBsKCk7XG4gICAgICBhd2FpdCBiYWNrZW5kLmluaXRpYWxpemUoZW52LCBncHVBZGFwdGVyISk7XG5cbiAgICAgIGpzZXBJbml0KCd3ZWJncHUnLCBbXG4gICAgICAgIC8vIGJhY2tlbmRcbiAgICAgICAgYmFja2VuZCxcblxuICAgICAgICAvLyBqc2VwQWxsb2MoKVxuICAgICAgICAoc2l6ZTogbnVtYmVyKSA9PiBiYWNrZW5kLmFsbG9jKE51bWJlcihzaXplKSksXG5cbiAgICAgICAgLy8ganNlcEZyZWUoKVxuICAgICAgICAocHRyOiBudW1iZXIpID0+IGJhY2tlbmQuZnJlZShwdHIpLFxuXG4gICAgICAgIC8vIGpzZXBDb3B5KHNyYywgZHN0LCBzaXplLCBpc1NvdXJjZUdwdSlcbiAgICAgICAgKHNyYzogbnVtYmVyLCBkc3Q6IG51bWJlciwgc2l6ZTogbnVtYmVyLCBpc1NvdXJjZUdwdSA9IGZhbHNlKSA9PiB7XG4gICAgICAgICAgaWYgKGlzU291cmNlR3B1KSB7XG4gICAgICAgICAgICBMT0dfREVCVUcoXG4gICAgICAgICAgICAgICd2ZXJib3NlJyxcbiAgICAgICAgICAgICAgKCkgPT4gYFtXZWJHUFVdIGpzZXBDb3B5R3B1VG9HcHU6IHNyYz0ke051bWJlcihzcmMpfSwgZHN0PSR7TnVtYmVyKGRzdCl9LCBzaXplPSR7TnVtYmVyKHNpemUpfWAsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgYmFja2VuZC5tZW1jcHkoTnVtYmVyKHNyYyksIE51bWJlcihkc3QpKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTE9HX0RFQlVHKFxuICAgICAgICAgICAgICAndmVyYm9zZScsXG4gICAgICAgICAgICAgICgpID0+XG4gICAgICAgICAgICAgICAgYFtXZWJHUFVdIGpzZXBDb3B5Q3B1VG9HcHU6IGRhdGFPZmZzZXQ9JHtOdW1iZXIoc3JjKX0sIGdwdURhdGFJZD0ke051bWJlcihkc3QpfSwgc2l6ZT0ke051bWJlcihzaXplKX1gLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBtb2R1bGUuSEVBUFU4LnN1YmFycmF5KE51bWJlcihzcmMgPj4+IDApLCBOdW1iZXIoc3JjID4+PiAwKSArIE51bWJlcihzaXplKSk7XG4gICAgICAgICAgICBiYWNrZW5kLnVwbG9hZChOdW1iZXIoZHN0KSwgZGF0YSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuXG4gICAgICAgIC8vIGpzZXBDb3B5QXN5bmMoc3JjLCBkc3QsIHNpemUpXG4gICAgICAgIGFzeW5jIChncHVEYXRhSWQ6IG51bWJlciwgZGF0YU9mZnNldDogbnVtYmVyLCBzaXplOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgICBMT0dfREVCVUcoXG4gICAgICAgICAgICAndmVyYm9zZScsXG4gICAgICAgICAgICAoKSA9PiBgW1dlYkdQVV0ganNlcENvcHlHcHVUb0NwdTogZ3B1RGF0YUlkPSR7Z3B1RGF0YUlkfSwgZGF0YU9mZnNldD0ke2RhdGFPZmZzZXR9LCBzaXplPSR7c2l6ZX1gLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBhd2FpdCBiYWNrZW5kLmRvd25sb2FkKE51bWJlcihncHVEYXRhSWQpLCAoKSA9PlxuICAgICAgICAgICAgbW9kdWxlLkhFQVBVOC5zdWJhcnJheShOdW1iZXIoZGF0YU9mZnNldCkgPj4+IDAsIE51bWJlcihkYXRhT2Zmc2V0ICsgc2l6ZSkgPj4+IDApLFxuICAgICAgICAgICk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgLy8ganNlcENyZWF0ZUtlcm5lbFxuICAgICAgICAoa2VybmVsVHlwZTogc3RyaW5nLCBrZXJuZWxJZDogbnVtYmVyLCBhdHRyaWJ1dGU6IHVua25vd24pID0+XG4gICAgICAgICAgYmFja2VuZC5jcmVhdGVLZXJuZWwoXG4gICAgICAgICAgICBrZXJuZWxUeXBlLFxuICAgICAgICAgICAgTnVtYmVyKGtlcm5lbElkKSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZSxcbiAgICAgICAgICAgIG1vZHVsZS5VVEY4VG9TdHJpbmcobW9kdWxlLl9Kc2VwR2V0Tm9kZU5hbWUhKE51bWJlcihrZXJuZWxJZCkpKSxcbiAgICAgICAgICApLFxuXG4gICAgICAgIC8vIGpzZXBSZWxlYXNlS2VybmVsXG4gICAgICAgIChrZXJuZWw6IG51bWJlcikgPT4gYmFja2VuZC5yZWxlYXNlS2VybmVsKGtlcm5lbCksXG5cbiAgICAgICAgLy8ganNlcFJ1blxuICAgICAgICAoa2VybmVsOiBudW1iZXIsIGNvbnRleHREYXRhT2Zmc2V0OiBudW1iZXIsIHNlc3Npb25IYW5kbGU6IG51bWJlciwgZXJyb3JzOiBBcnJheTxQcm9taXNlPHN0cmluZyB8IG51bGw+PikgPT4ge1xuICAgICAgICAgIExPR19ERUJVRyhcbiAgICAgICAgICAgICd2ZXJib3NlJyxcbiAgICAgICAgICAgICgpID0+XG4gICAgICAgICAgICAgIGBbV2ViR1BVXSBqc2VwUnVuOiBzZXNzaW9uSGFuZGxlPSR7c2Vzc2lvbkhhbmRsZX0sIGtlcm5lbD0ke2tlcm5lbH0sIGNvbnRleHREYXRhT2Zmc2V0PSR7Y29udGV4dERhdGFPZmZzZXR9YCxcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSBuZXcgQ29tcHV0ZUNvbnRleHRJbXBsKG1vZHVsZSwgYmFja2VuZCwgTnVtYmVyKGNvbnRleHREYXRhT2Zmc2V0KSk7XG4gICAgICAgICAgcmV0dXJuIGJhY2tlbmQuY29tcHV0ZUtlcm5lbChOdW1iZXIoa2VybmVsKSwgY29udGV4dCwgZXJyb3JzKTtcbiAgICAgICAgfSxcbiAgICAgICAgLy8ganNlcENhcHR1cmVCZWdpblxuICAgICAgICAoKSA9PiBiYWNrZW5kLmNhcHR1cmVCZWdpbigpLFxuICAgICAgICAvLyBqc2VwQ2FwdHVyZUVuZFxuICAgICAgICAoKSA9PiBiYWNrZW5kLmNhcHR1cmVFbmQoKSxcbiAgICAgICAgLy8ganNlcFJlcGxheVxuICAgICAgICAoKSA9PiBiYWNrZW5kLnJlcGxheSgpLFxuICAgICAgXSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGNvbnN0IGJhY2tlbmQgPSBuZXcgV2ViTk5CYWNrZW5kKGVudik7XG4gICAganNlcEluaXQoJ3dlYm5uJywgW1xuICAgICAgYmFja2VuZCxcbiAgICAgIC8vIGpzZXBSZXNlcnZlVGVuc29ySWRcbiAgICAgICgpID0+IGJhY2tlbmQucmVzZXJ2ZVRlbnNvcklkKCksXG4gICAgICAvLyBqc2VwUmVsZWFzZVRlbnNvcklkLFxuICAgICAgKHRlbnNvcklkOiBudW1iZXIpID0+IGJhY2tlbmQucmVsZWFzZVRlbnNvcklkKHRlbnNvcklkKSxcbiAgICAgIC8vIGpzZXBFbnN1cmVUZW5zb3JcbiAgICAgIGFzeW5jIChzZXNzaW9uSWQ6IG51bWJlciB8IHVuZGVmaW5lZCwgdGVuc29ySWQ6IG51bWJlciwgb25ueERhdGFUeXBlOiBudW1iZXIsIHNoYXBlOiBudW1iZXJbXSwgY29weU9sZCkgPT5cbiAgICAgICAgYmFja2VuZC5lbnN1cmVUZW5zb3Ioc2Vzc2lvbklkLCB0ZW5zb3JJZCwgb25ueERhdGFUeXBlLCBzaGFwZSwgY29weU9sZCksXG4gICAgICAvLyBqc2VwVXBsb2FkVGVuc29yXG4gICAgICAodGVuc29ySWQ6IG51bWJlciwgZGF0YTogVWludDhBcnJheSkgPT4ge1xuICAgICAgICBiYWNrZW5kLnVwbG9hZFRlbnNvcih0ZW5zb3JJZCwgZGF0YSk7XG4gICAgICB9LFxuICAgICAgLy8ganNlcERvd25sb2FkVGVuc29yXG4gICAgICBhc3luYyAodGVuc29ySWQ6IG51bWJlciwgZHN0QnVmZmVyOiBBcnJheUJ1ZmZlclZpZXcgfCBBcnJheUJ1ZmZlcikgPT4gYmFja2VuZC5kb3dubG9hZFRlbnNvcih0ZW5zb3JJZCwgZHN0QnVmZmVyKSxcbiAgICBdKTtcbiAgfVxufTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuLy8gV2ViTk4gQVBJIGN1cnJlbnRseSBkb2VzIG5vdCBoYXZlIGEgVHlwZVNjcmlwdCBkZWZpbml0aW9uIGZpbGUuIFRoaXMgZmlsZSBpcyBhIHdvcmthcm91bmQgd2l0aCB0eXBlcyBnZW5lcmF0ZWQgZnJvbVxuLy8gV2ViTk4gQVBJIHNwZWNpZmljYXRpb24uXG4vLyBodHRwczovL2dpdGh1Yi5jb20vd2VibWFjaGluZWxlYXJuaW5nL3dlYm5uL2lzc3Vlcy82Nzdcbi8vLyA8cmVmZXJlbmNlIHBhdGg9XCJqc2VwL3dlYm5uL3dlYm5uLmQudHNcIiAvPlxuXG5pbXBvcnQgeyBFbnYsIEluZmVyZW5jZVNlc3Npb24sIFRlbnNvciB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7XG4gIFNlcmlhbGl6YWJsZUludGVybmFsQnVmZmVyLFxuICBTZXJpYWxpemFibGVTZXNzaW9uTWV0YWRhdGEsXG4gIFNlcmlhbGl6YWJsZVRlbnNvck1ldGFkYXRhLFxuICBUZW5zb3JNZXRhZGF0YSxcbn0gZnJvbSAnLi9wcm94eS1tZXNzYWdlcyc7XG5pbXBvcnQgeyBzZXRSdW5PcHRpb25zIH0gZnJvbSAnLi9ydW4tb3B0aW9ucyc7XG5pbXBvcnQgeyBzZXRTZXNzaW9uT3B0aW9ucyB9IGZyb20gJy4vc2Vzc2lvbi1vcHRpb25zJztcbmltcG9ydCB7XG4gIGNhbGN1bGF0ZVRlbnNvclNpemVJbkJ5dGVzLFxuICBkYXRhTG9jYXRpb25TdHJpbmdUb0VudW0sXG4gIGlzR3B1QnVmZmVyU3VwcG9ydGVkVHlwZSxcbiAgaXNNTFRlbnNvclN1cHBvcnRlZFR5cGUsXG4gIGxvZ0xldmVsU3RyaW5nVG9FbnVtLFxuICB0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyxcbiAgdGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0sXG4gIHRlbnNvclR5cGVUb1R5cGVkQXJyYXlDb25zdHJ1Y3Rvcixcbn0gZnJvbSAnLi93YXNtLWNvbW1vbic7XG5pbXBvcnQgeyBnZXRJbnN0YW5jZSB9IGZyb20gJy4vd2FzbS1mYWN0b3J5JztcbmltcG9ydCB7IGFsbG9jV2FzbVN0cmluZywgY2hlY2tMYXN0RXJyb3IgfSBmcm9tICcuL3dhc20tdXRpbHMnO1xuaW1wb3J0IHsgbG9hZEZpbGUgfSBmcm9tICcuL3dhc20tdXRpbHMtbG9hZC1maWxlJztcblxuLy8gI3JlZ2lvbiBJbml0aWFsaXphdGlvbnNcblxuLyoqXG4gKiBUaGVyZSBhcmUgNCBkaWZmZXJlbnQgXCJpbml0aWFsaXphdGlvblwiIHN0ZXBzIGZvciBPUlQuIFRoZXkgaGFwcGVuIGluIGRpZmZlcmVudCBwbGFjZXMgYW5kIGRpZmZlcmVudCB0aW1lLlxuICpcbiAqIDEuIEphdmFTY3JpcHQgaW5pdGlhbGl6YXRpb24gZm9yIG9ubnhydW50aW1lLWNvbW1vbiBhbmQgb25ueHJ1bnRpbWUtd2ViLlxuICogICAgVGhpcyBpcyB0aGUgZmlyc3QgaW5pdGlhbGl6YXRpb24gc3RlcC4gSW4gdGhpcyBzdGVwLCBvbm54cnVudGltZS13ZWIgY2FsbHMgb25ueHJ1bnRpbWUtY29tbW9uJ3MgcmVnaXN0ZXJCYWNrZW5kKClcbiAqIGZ1bmN0aW9uIG11bHRpcGxlIHRpbWVzIHRvIHJlZ2lzdGVyIGFsbCB0aGUgYXZhaWxhYmxlIGJhY2tlbmRzLiBUaGUgYmFja2VuZCByZWdpc3RyYXRpb24gaXMgdmVyeSBmYXN0LiBJdCBvbmx5XG4gKiByZWdpc3RlcnMgdGhlIGJhY2tlbmQgbmFtZSB3aXRoIHRoZSB1bmluaXRpYWxpemVkIGJhY2tlbmQgb2JqZWN0LiBObyBoZWF2eSBpbml0aWFsaXphdGlvbiBpcyBkb25lIGluIHRoaXMgc3RlcC5cbiAqICAgIFJlZmVyIHRvIHdlYi9saWIvaW5kZXgudHMgZm9yIHRoZSBiYWNrZW5kIHJlZ2lzdHJhdGlvbi5cbiAqXG4gKiAyLiBXZWJBc3NlbWJseSBhcnRpZmFjdCBpbml0aWFsaXphdGlvbi5cbiAqICAgIFRoaXMgaGFwcGVucyB3aGVuIGFueSByZWdpc3RlcmVkIHdhc20gYmFja2VuZCBpcyB1c2VkIGZvciB0aGUgZmlyc3QgdGltZSAoaWUuIGBvcnQuSW5mZXJlbmNlU2Vzc2lvbi5jcmVhdGUoKWAgaXNcbiAqIGNhbGxlZCkuIEluIHRoaXMgc3RlcCwgb25ueHJ1bnRpbWUtd2ViIGRvZXMgdGhlIGZvbGxvd2luZ3M6XG4gKiAgICAgLSBjcmVhdGUgYSBwcm94eSB3b3JrZXIgYW5kIG1ha2Ugc3VyZSB0aGUgcHJveHkgd29ya2VyIGlzIHJlYWR5IHRvIHJlY2VpdmUgbWVzc2FnZXMsIGlmIHByb3h5IGlzIGVuYWJsZWQuXG4gKiAgICAgLSBwZXJmb3JtIGZlYXR1cmUgZGV0ZWN0aW9uLCBsb2NhdGUgY29ycmVjdCBXZWJBc3NlbWJseSBhcnRpZmFjdCBwYXRoIGFuZCBjYWxsIHRoZSBFbXNjcmlwdGVuIGdlbmVyYXRlZFxuICogSmF2YVNjcmlwdCBjb2RlIHRvIGluaXRpYWxpemUgdGhlIFdlYkFzc2VtYmx5IHJ1bnRpbWUuXG4gKiAgICAgICAgIC0gaWYgcHJveHkgaXMgZW5hYmxlZCwgdGhpcyBzdGVwIGhhcHBlbnMgaW4gdGhlIHByb3h5IHdvcmtlciB1c2luZyBtZXNzYWdlICdpbml0LXdhc20nLlxuICogICAgICAgICAtIGRvd25sb2FkaW5nIHRoZSAnb3J0LXdhc217Li4ufS53YXNtJyBmaWxlIGlzIGRvbmUgaW4gdGhpcyBzdGVwLlxuICogICAgICAgICAtIGlmIG11bHRpLXRocmVhZCBpcyBlbmFibGVkLCBvbmUgb3IgbW9yZSB3ZWJ3b3JrZXIgd2lsbCBiZSBjcmVhdGVkIHRvIGluaXRpYWxpemUgdGhlIFBUaHJlYWQgdGhyZWFkcG9vbC5cbiAqXG4gKiAzLiBPUlQgZW52aXJvbm1lbnQgaW5pdGlhbGl6YXRpb24uXG4gKiAgICBUaGlzIGhhcHBlbnMgYWZ0ZXIgc3RlcCAyLiBJbiB0aGlzIHN0ZXAsIG9ubnhydW50aW1lLXdlYiBwZXJmb3JtcyBPTk5YIFJ1bnRpbWUgZW52aXJvbm1lbnQgaW5pdGlhbGl6YXRpb24uXG4gKiBGdW5jdGlvbiBgX09ydEluaXQoKWAgaXMgY2FsbGVkIGluIHRoaXMgc3RlcC5cbiAqICAgICAtIGlmIHByb3h5IGlzIGVuYWJsZWQsIHRoaXMgc3RlcCBoYXBwZW5zIGluIHRoZSBwcm94eSB3b3JrZXIgdXNpbmcgbWVzc2FnZSAnaW5pdC1vcnQnLlxuICogICAgIC0gbG9nZ2luZyBsZXZlbCAob3J0LmVudi5sb2dMZXZlbCkgYW5kIHRocmVhZCBudW1iZXIgKG9ydC5lbnYud2FzbS5udW1UaHJlYWRzKSBhcmUgc2V0IGluIHRoaXMgc3RlcC5cbiAqXG4gKiA0LiBTZXNzaW9uIGluaXRpYWxpemF0aW9uLlxuICogICAgVGhpcyBoYXBwZW5zIHdoZW4gYG9ydC5JbmZlcmVuY2VTZXNzaW9uLmNyZWF0ZSgpYCBpcyBjYWxsZWQuIFVubGlrZSB0aGUgZmlyc3QgMyBzdGVwcyAodGhleSBvbmx5IGNhbGxlZCBvbmNlKSxcbiAqIHRoaXMgc3RlcCB3aWxsIGJlIGRvbmUgZm9yIGVhY2ggc2Vzc2lvbi4gSW4gdGhpcyBzdGVwLCBvbm54cnVudGltZS13ZWIgZG9lcyB0aGUgZm9sbG93aW5nczpcbiAqICAgIElmIHRoZSBwYXJhbWV0ZXIgaXMgYSBVUkw6XG4gKiAgICAtIGRvd25sb2FkIHRoZSBtb2RlbCBkYXRhIGZyb20gdGhlIFVSTC5cbiAqICAgIC0gY29weSB0aGUgbW9kZWwgZGF0YSB0byB0aGUgV0FTTSBoZWFwLiAocHJveHk6ICdjb3B5LWZyb20nKVxuICogICAgLSBkZXJlZmVyZW5jZSB0aGUgbW9kZWwgYnVmZmVyLiBUaGlzIHN0ZXAgYWxsb3dzIHRoZSBvcmlnaW5hbCBBcnJheUJ1ZmZlciB0byBiZSBnYXJiYWdlIGNvbGxlY3RlZC5cbiAqICAgIC0gY2FsbCBgX09ydENyZWF0ZVNlc3Npb24oKWAgdG8gY3JlYXRlIHRoZSBzZXNzaW9uLiAocHJveHk6ICdjcmVhdGUnKVxuICpcbiAqICAgIElmIHRoZSBwYXJhbWV0ZXIgaXMgYSBVaW50OEFycmF5IG9iamVjdDpcbiAqICAgIC0gY29weSB0aGUgbW9kZWwgZGF0YSB0byB0aGUgV0FTTSBoZWFwLiAocHJveHk6ICdjb3B5LWZyb20nKVxuICogICAgLSBjYWxsIGBfT3J0Q3JlYXRlU2Vzc2lvbigpYCB0byBjcmVhdGUgdGhlIHNlc3Npb24uIChwcm94eTogJ2NyZWF0ZScpXG4gKlxuICpcbiAqL1xuXG4vKipcbiAqIGluaXRpYWxpemUgT1JUIGVudmlyb25tZW50LlxuICpcbiAqIEBwYXJhbSBudW1UaHJlYWRzIFNldEdsb2JhbEludHJhT3BOdW1UaHJlYWRzKG51bVRocmVhZHMpXG4gKiBAcGFyYW0gbG9nZ2luZ0xldmVsIENyZWF0ZUVudihzdGF0aWNfY2FzdDxPcnRMb2dnaW5nTGV2ZWw+KGxvZ2dpbmdfbGV2ZWwpKVxuICovXG5jb25zdCBpbml0T3J0ID0gKG51bVRocmVhZHM6IG51bWJlciwgbG9nZ2luZ0xldmVsOiBudW1iZXIpOiB2b2lkID0+IHtcbiAgY29uc3QgZXJyb3JDb2RlID0gZ2V0SW5zdGFuY2UoKS5fT3J0SW5pdChudW1UaHJlYWRzLCBsb2dnaW5nTGV2ZWwpO1xuICBpZiAoZXJyb3JDb2RlICE9PSAwKSB7XG4gICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBpbml0aWFsaXplIG9ubnhydW50aW1lLlwiKTtcbiAgfVxufTtcblxuLyoqXG4gKiBpbml0aWFsaXplIHJ1bnRpbWUgZW52aXJvbm1lbnQuXG4gKiBAcGFyYW0gZW52IHBhc3NlZCBpbiB0aGUgZW52aXJvbm1lbnQgY29uZmlnIG9iamVjdC5cbiAqL1xuZXhwb3J0IGNvbnN0IGluaXRSdW50aW1lID0gYXN5bmMgKGVudjogRW52KTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIC8vIGluaXQgT1JUXG4gIGluaXRPcnQoZW52Lndhc20ubnVtVGhyZWFkcyEsIGxvZ0xldmVsU3RyaW5nVG9FbnVtKGVudi5sb2dMZXZlbCkpO1xufTtcblxuLyoqXG4gKiBwZXJmb3JtIEVQIHNwZWNpZmljIGluaXRpYWxpemF0aW9uLlxuICpcbiAqIEBwYXJhbSBlbnZcbiAqIEBwYXJhbSBlcE5hbWVcbiAqL1xuZXhwb3J0IGNvbnN0IGluaXRFcCA9IGFzeW5jIChlbnY6IEVudiwgZXBOYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgLy8gaW5pdGlhbGl6ZSBBU1lOQ0lGWSBzdXBwb3J0XG4gIGdldEluc3RhbmNlKCkuYXN5bmNJbml0Py4oKTtcblxuICBpZiAoZXBOYW1lID09PSAnd2ViZ3B1JyAmJiBCVUlMRF9ERUZTLlVTRV9XRUJHUFVfRVApIHtcbiAgICBnZXRJbnN0YW5jZSgpLndlYmdwdUluaXQhKChkZXZpY2UpID0+IHtcbiAgICAgIGVudi53ZWJncHUuZGV2aWNlID0gZGV2aWNlO1xuICAgIH0pO1xuICB9XG5cbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfSlNFUCkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzXG4gICAgY29uc3QgaW5pdEpzZXAgPSByZXF1aXJlKCcuL2pzZXAvaW5pdCcpLmluaXQ7XG5cbiAgICBpZiAoZXBOYW1lID09PSAnd2ViZ3B1JyAmJiAhQlVJTERfREVGUy5VU0VfV0VCR1BVX0VQKSB7XG4gICAgICAvLyBwZXJmb3JtIFdlYkdQVSBhdmFpbGFiaWxpdHkgY2hlY2tcbiAgICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yID09PSAndW5kZWZpbmVkJyB8fCAhbmF2aWdhdG9yLmdwdSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dlYkdQVSBpcyBub3Qgc3VwcG9ydGVkIGluIGN1cnJlbnQgZW52aXJvbm1lbnQnKTtcbiAgICAgIH1cblxuICAgICAgbGV0IGFkYXB0ZXIgPSBlbnYud2ViZ3B1LmFkYXB0ZXIgYXMgR1BVQWRhcHRlciB8IG51bGw7XG4gICAgICBpZiAoIWFkYXB0ZXIpIHtcbiAgICAgICAgLy8gaWYgYWRhcHRlciBpcyBub3Qgc2V0LCByZXF1ZXN0IGEgbmV3IGFkYXB0ZXIuXG4gICAgICAgIGNvbnN0IHBvd2VyUHJlZmVyZW5jZSA9IGVudi53ZWJncHUucG93ZXJQcmVmZXJlbmNlO1xuICAgICAgICBpZiAoXG4gICAgICAgICAgcG93ZXJQcmVmZXJlbmNlICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICBwb3dlclByZWZlcmVuY2UgIT09ICdsb3ctcG93ZXInICYmXG4gICAgICAgICAgcG93ZXJQcmVmZXJlbmNlICE9PSAnaGlnaC1wZXJmb3JtYW5jZSdcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHBvd2VyUHJlZmVyZW5jZSBzZXR0aW5nOiBcIiR7cG93ZXJQcmVmZXJlbmNlfVwiYCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZm9yY2VGYWxsYmFja0FkYXB0ZXIgPSBlbnYud2ViZ3B1LmZvcmNlRmFsbGJhY2tBZGFwdGVyO1xuICAgICAgICBpZiAoZm9yY2VGYWxsYmFja0FkYXB0ZXIgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgZm9yY2VGYWxsYmFja0FkYXB0ZXIgIT09ICdib29sZWFuJykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBmb3JjZUZhbGxiYWNrQWRhcHRlciBzZXR0aW5nOiBcIiR7Zm9yY2VGYWxsYmFja0FkYXB0ZXJ9XCJgKTtcbiAgICAgICAgfVxuICAgICAgICBhZGFwdGVyID0gYXdhaXQgbmF2aWdhdG9yLmdwdS5yZXF1ZXN0QWRhcHRlcih7IHBvd2VyUHJlZmVyZW5jZSwgZm9yY2VGYWxsYmFja0FkYXB0ZXIgfSk7XG4gICAgICAgIGlmICghYWRhcHRlcikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICdGYWlsZWQgdG8gZ2V0IEdQVSBhZGFwdGVyLiAnICtcbiAgICAgICAgICAgICAgJ1lvdSBtYXkgbmVlZCB0byBlbmFibGUgZmxhZyBcIi0tZW5hYmxlLXVuc2FmZS13ZWJncHVcIiBpZiB5b3UgYXJlIHVzaW5nIENocm9tZS4nLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGlmIGFkYXB0ZXIgaXMgc2V0LCB2YWxpZGF0ZSBpdC5cbiAgICAgICAgaWYgKFxuICAgICAgICAgIHR5cGVvZiBhZGFwdGVyLmxpbWl0cyAhPT0gJ29iamVjdCcgfHxcbiAgICAgICAgICB0eXBlb2YgYWRhcHRlci5mZWF0dXJlcyAhPT0gJ29iamVjdCcgfHxcbiAgICAgICAgICB0eXBlb2YgYWRhcHRlci5yZXF1ZXN0RGV2aWNlICE9PSAnZnVuY3Rpb24nXG4gICAgICAgICkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBHUFUgYWRhcHRlciBzZXQgaW4gYGVudi53ZWJncHUuYWRhcHRlcmAuIEl0IG11c3QgYmUgYSBHUFVBZGFwdGVyIG9iamVjdC4nKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBhd2FpdCBpbml0SnNlcCgnd2ViZ3B1JywgZ2V0SW5zdGFuY2UoKSwgZW52LCBhZGFwdGVyKTtcbiAgICB9XG4gICAgaWYgKGVwTmFtZSA9PT0gJ3dlYm5uJykge1xuICAgICAgLy8gcGVyZm9ybSBXZWJOTiBhdmFpbGFiaWxpdHkgY2hlY2tcbiAgICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yID09PSAndW5kZWZpbmVkJyB8fCAhKG5hdmlnYXRvciBhcyB1bmtub3duIGFzIHsgbWw6IHVua25vd24gfSkubWwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdXZWJOTiBpcyBub3Qgc3VwcG9ydGVkIGluIGN1cnJlbnQgZW52aXJvbm1lbnQnKTtcbiAgICAgIH1cblxuICAgICAgYXdhaXQgaW5pdEpzZXAoJ3dlYm5uJywgZ2V0SW5zdGFuY2UoKSwgZW52KTtcbiAgICB9XG4gIH1cbn07XG5cbi8vICNlbmRyZWdpb24gSW5pdGlhbGl6YXRpb25zXG5cbi8qKlxuICogdmFsaWQgZGF0YSBsb2NhdGlvbnMgZm9yIGlucHV0L291dHB1dCB0ZW5zb3JzLlxuICovXG50eXBlIFN1cHBvcnRlZFRlbnNvckRhdGFMb2NhdGlvbkZvcklucHV0T3V0cHV0ID1cbiAgfCAnY3B1J1xuICB8ICdjcHUtcGlubmVkJ1xuICB8ICdncHUtYnVmZmVyJ1xuICB8ICdtbC10ZW5zb3InXG4gIC8vIFVzZSAnbWwtdGVuc29yJyBkdXJpbmcgaW5mZXJlbmNlLCBidXQgb3V0cHV0IGEgdGVuc29yIGxvY2F0ZWQgb24gdGhlIENQVS5cbiAgfCAnbWwtdGVuc29yLWNwdS1vdXRwdXQnO1xuXG50eXBlIElPQmluZGluZ1N0YXRlID0ge1xuICAvKipcbiAgICogdGhlIGhhbmRsZSBvZiBJTyBiaW5kaW5nLlxuICAgKi9cbiAgcmVhZG9ubHkgaGFuZGxlOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIHRoZSBwcmVmZXJyZWQgbG9jYXRpb24gZm9yIGVhY2ggb3V0cHV0IHRlbnNvci5cbiAgICpcbiAgICogdmFsdWUgaXMgb25lIG9mICdjcHUnLCAnY3B1LXBpbm5lZCcsICdncHUtYnVmZmVyJywgJ21sLXRlbnNvcicuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnM6IHJlYWRvbmx5IFN1cHBvcnRlZFRlbnNvckRhdGFMb2NhdGlvbkZvcklucHV0T3V0cHV0W107XG5cbiAgLyoqXG4gICAqIGVudW0gdmFsdWUgb2YgdGhlIHByZWZlcnJlZCBsb2NhdGlvbiBmb3IgZWFjaCBvdXRwdXQgdGVuc29yLlxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zRW5jb2RlZDogcmVhZG9ubHkgbnVtYmVyW107XG59O1xuXG4vKipcbiAqICB0dXBsZSBlbGVtZW50cyBhcmU6IEluZmVyZW5jZVNlc3Npb24gSUQ7IGlucHV0TmFtZXNVVEY4RW5jb2RlZDsgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZDsgYmluZGluZ1N0YXRlXG4gKi9cbnR5cGUgU2Vzc2lvbk1ldGFkYXRhID0gW1xuICBpbmZlcmVuY2VTZXNzaW9uSWQ6IG51bWJlcixcbiAgaW5wdXROYW1lc1VURjhFbmNvZGVkOiBudW1iZXJbXSxcbiAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZDogbnVtYmVyW10sXG4gIGJpbmRpbmdTdGF0ZTogSU9CaW5kaW5nU3RhdGUgfCBudWxsLFxuICBlbmFibGVHcmFwaENhcHR1cmU6IGJvb2xlYW4sXG4gIGlucHV0T3V0cHV0Qm91bmQ6IGJvb2xlYW4sXG5dO1xuXG5jb25zdCBhY3RpdmVTZXNzaW9ucyA9IG5ldyBNYXA8bnVtYmVyLCBTZXNzaW9uTWV0YWRhdGE+KCk7XG5cbi8qKlxuICogZ2V0IHRoZSBpbnB1dC9vdXRwdXQgY291bnQgb2YgdGhlIHNlc3Npb24uXG4gKiBAcGFyYW0gc2Vzc2lvbkhhbmRsZSB0aGUgaGFuZGxlIHJlcHJlc2VudGluZyB0aGUgc2Vzc2lvbi4gc2hvdWxkIGJlIG5vbi16ZXJvLlxuICogQHJldHVybnMgYSB0dXBsZSBpbmNsdWRpbmcgMiBudW1iZXJzLCByZXByZXNlbnRpbmcgdGhlIGlucHV0IGNvdW50IGFuZCBvdXRwdXQgY291bnQuXG4gKi9cbmNvbnN0IGdldFNlc3Npb25JbnB1dE91dHB1dENvdW50ID0gKHNlc3Npb25IYW5kbGU6IG51bWJlcik6IFtudW1iZXIsIG51bWJlcl0gPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgY29uc3Qgc3RhY2sgPSB3YXNtLnN0YWNrU2F2ZSgpO1xuICB0cnkge1xuICAgIGNvbnN0IHB0clNpemUgPSB3YXNtLlBUUl9TSVpFO1xuICAgIGNvbnN0IGRhdGFPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2MoMiAqIHB0clNpemUpO1xuICAgIGNvbnN0IGVycm9yQ29kZSA9IHdhc20uX09ydEdldElucHV0T3V0cHV0Q291bnQoc2Vzc2lvbkhhbmRsZSwgZGF0YU9mZnNldCwgZGF0YU9mZnNldCArIHB0clNpemUpO1xuICAgIGlmIChlcnJvckNvZGUgIT09IDApIHtcbiAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgZ2V0IHNlc3Npb24gaW5wdXQvb3V0cHV0IGNvdW50LlwiKTtcbiAgICB9XG4gICAgY29uc3QgdHlwZSA9IHB0clNpemUgPT09IDQgPyAnaTMyJyA6ICdpNjQnO1xuICAgIHJldHVybiBbTnVtYmVyKHdhc20uZ2V0VmFsdWUoZGF0YU9mZnNldCwgdHlwZSkpLCBOdW1iZXIod2FzbS5nZXRWYWx1ZShkYXRhT2Zmc2V0ICsgcHRyU2l6ZSwgdHlwZSkpXTtcbiAgfSBmaW5hbGx5IHtcbiAgICB3YXNtLnN0YWNrUmVzdG9yZShzdGFjayk7XG4gIH1cbn07XG5cbmNvbnN0IGdldFNlc3Npb25JbnB1dE91dHB1dE1ldGFkYXRhID0gKFxuICBzZXNzaW9uSGFuZGxlOiBudW1iZXIsXG4gIGluZGV4OiBudW1iZXIsXG4pOiBbbmFtZU9mZnNldDogbnVtYmVyLCBlbGVtZW50VHlwZTogbnVtYmVyLCBkaW1zPzogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPl0gPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgY29uc3Qgc3RhY2sgPSB3YXNtLnN0YWNrU2F2ZSgpO1xuICBsZXQgbWV0YWRhdGFPZmZzZXQgPSAwO1xuICB0cnkge1xuICAgIGNvbnN0IHB0clNpemUgPSB3YXNtLlBUUl9TSVpFO1xuICAgIGNvbnN0IGRhdGFPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2MoMiAqIHB0clNpemUpO1xuICAgIGNvbnN0IGVycm9yQ29kZSA9IHdhc20uX09ydEdldElucHV0T3V0cHV0TWV0YWRhdGEoc2Vzc2lvbkhhbmRsZSwgaW5kZXgsIGRhdGFPZmZzZXQsIGRhdGFPZmZzZXQgKyBwdHJTaXplKTtcbiAgICBpZiAoZXJyb3JDb2RlICE9PSAwKSB7XG4gICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IGdldCBzZXNzaW9uIGlucHV0L291dHB1dCBtZXRhZGF0YS5cIik7XG4gICAgfVxuICAgIGNvbnN0IG5hbWVPZmZzZXQgPSBOdW1iZXIod2FzbS5nZXRWYWx1ZShkYXRhT2Zmc2V0LCAnKicpKTtcbiAgICBtZXRhZGF0YU9mZnNldCA9IE51bWJlcih3YXNtLmdldFZhbHVlKGRhdGFPZmZzZXQgKyBwdHJTaXplLCAnKicpKTtcbiAgICAvLyBnZXQgZWxlbWVudCB0eXBlXG4gICAgY29uc3QgZWxlbWVudFR5cGUgPSB3YXNtLkhFQVAzMlttZXRhZGF0YU9mZnNldCAvIDRdO1xuICAgIGlmIChlbGVtZW50VHlwZSA9PT0gMCkge1xuICAgICAgcmV0dXJuIFtuYW1lT2Zmc2V0LCAwXTsgLy8gbm9uLXRlbnNvclxuICAgIH1cblxuICAgIC8vIGdldCBkaW1zIGNvdW50XG4gICAgY29uc3QgZGltc0NvdW50ID0gd2FzbS5IRUFQVTMyW21ldGFkYXRhT2Zmc2V0IC8gNCArIDFdO1xuICAgIC8vIGdldCBkaW1zXG4gICAgY29uc3QgZGltczogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPiA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGltc0NvdW50OyBpKyspIHtcbiAgICAgIGNvbnN0IHN5bWJvbGljRGltTmFtZU9mZnNldCA9IE51bWJlcih3YXNtLmdldFZhbHVlKG1ldGFkYXRhT2Zmc2V0ICsgOCArIGkgKiBwdHJTaXplLCAnKicpKTtcbiAgICAgIGRpbXMucHVzaChcbiAgICAgICAgc3ltYm9saWNEaW1OYW1lT2Zmc2V0ICE9PSAwXG4gICAgICAgICAgPyB3YXNtLlVURjhUb1N0cmluZyhzeW1ib2xpY0RpbU5hbWVPZmZzZXQpXG4gICAgICAgICAgOiBOdW1iZXIod2FzbS5nZXRWYWx1ZShtZXRhZGF0YU9mZnNldCArIDggKyAoaSArIGRpbXNDb3VudCkgKiBwdHJTaXplLCAnKicpKSxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBbbmFtZU9mZnNldCwgZWxlbWVudFR5cGUsIGRpbXNdO1xuICB9IGZpbmFsbHkge1xuICAgIHdhc20uc3RhY2tSZXN0b3JlKHN0YWNrKTtcbiAgICBpZiAobWV0YWRhdGFPZmZzZXQgIT09IDApIHtcbiAgICAgIHdhc20uX09ydEZyZWUobWV0YWRhdGFPZmZzZXQpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBhbGxvY2F0ZSB0aGUgbWVtb3J5IGFuZCBtZW1jcHkgdGhlIGV4dGVybmFsIGJ1ZmZlci5cbiAqXG4gKiBAcGFyYW0gbW9kZWwgLSB0aGUgZXh0ZXJuYWwgYnVmZmVyIGNvbnRhaW5pbmcgdGhlIG1vZGVsIGRhdGEuIE11c3Qgbm90IGJlIHRoZSBzYW1lIGJ1ZmZlciBhcyB0aGUgV0FTTSBoZWFwLlxuICogQHJldHVybnMgYSAyLWVsZW1lbnRzIHR1cGxlIC0gdGhlIHBvaW50ZXIgYW5kIHNpemUgb2YgdGhlIGFsbG9jYXRlZCBidWZmZXJcbiAqL1xuZXhwb3J0IGNvbnN0IGNvcHlGcm9tRXh0ZXJuYWxCdWZmZXIgPSAobW9kZWw6IFVpbnQ4QXJyYXkpOiBbbnVtYmVyLCBudW1iZXJdID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gIGNvbnN0IG1vZGVsRGF0YU9mZnNldCA9IHdhc20uX21hbGxvYyhtb2RlbC5ieXRlTGVuZ3RoKTtcbiAgaWYgKG1vZGVsRGF0YU9mZnNldCA9PT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3QgY3JlYXRlIGEgc2Vzc2lvbi4gZmFpbGVkIHRvIGFsbG9jYXRlIGEgYnVmZmVyIG9mIHNpemUgJHttb2RlbC5ieXRlTGVuZ3RofS5gKTtcbiAgfVxuICB3YXNtLkhFQVBVOC5zZXQobW9kZWwsIG1vZGVsRGF0YU9mZnNldCk7XG4gIHJldHVybiBbbW9kZWxEYXRhT2Zmc2V0LCBtb2RlbC5ieXRlTGVuZ3RoXTtcbn07XG5cbi8qKlxuICogY3JlYXRlIGFuIGluZmVyZW5jZSBzZXNzaW9uIGZyb20gYSBtb2RlbCBkYXRhIGJ1ZmZlci5cbiAqXG4gKiBAcGFyYW0gbW9kZWxEYXRhIC0gZWl0aGVyIGEgVWludDhBcnJheSBvYmplY3QgcmVwcmVzZW50aW5nIHRoZSBtb2RlbCBkYXRhLCBvciBhIDItZWxlbWVudHMgdHVwbGUgY29udGFpbmluZyB0aGVcbiAqICAgICBwb2ludGVyIGFuZCBzaXplIG9mIHRoZSBtb2RlbCBkYXRhIGJ1ZmZlci5cbiAqIEBwYXJhbSBvcHRpb25zIGFuIG9wdGlvbmFsIHNlc3Npb24gb3B0aW9ucyBvYmplY3QuXG4gKiBAcmV0dXJucyBhIDMtZWxlbWVudHMgdHVwbGUgY29udGFpbmluZyBbc2Vzc2lvbiBoYW5kbGUsIGlucHV0IG5hbWVzLCBvdXRwdXQgbmFtZXNdXG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVTZXNzaW9uID0gYXN5bmMgKFxuICBtb2RlbERhdGE6IFVpbnQ4QXJyYXkgfCBTZXJpYWxpemFibGVJbnRlcm5hbEJ1ZmZlcixcbiAgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMsXG4pOiBQcm9taXNlPFNlcmlhbGl6YWJsZVNlc3Npb25NZXRhZGF0YT4gPT4ge1xuICBsZXQgbW9kZWxEYXRhT2Zmc2V0OiBudW1iZXIsIG1vZGVsRGF0YUxlbmd0aDogbnVtYmVyO1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcblxuICBpZiAoQXJyYXkuaXNBcnJheShtb2RlbERhdGEpKSB7XG4gICAgLy8gaWYgbW9kZWwgZGF0YSBpcyBhbiBhcnJheSwgaXQgbXVzdCBiZSBhIDItZWxlbWVudHMgdHVwbGUgY29udGFpbmluZyB0aGUgcG9pbnRlciBhbmQgc2l6ZSBvZiB0aGUgbW9kZWwgZGF0YVxuICAgIFttb2RlbERhdGFPZmZzZXQsIG1vZGVsRGF0YUxlbmd0aF0gPSBtb2RlbERhdGE7XG4gIH0gZWxzZSBpZiAobW9kZWxEYXRhLmJ1ZmZlciA9PT0gd2FzbS5IRUFQVTguYnVmZmVyKSB7XG4gICAgLy8gaWYgbW9kZWwgZGF0YSB1c2VzIHRoZSBzYW1lIGJ1ZmZlciBhcyB0aGUgV0FTTSBoZWFwLCB3ZSBkb24ndCBuZWVkIHRvIGNvcHkgaXQuXG4gICAgW21vZGVsRGF0YU9mZnNldCwgbW9kZWxEYXRhTGVuZ3RoXSA9IFttb2RlbERhdGEuYnl0ZU9mZnNldCwgbW9kZWxEYXRhLmJ5dGVMZW5ndGhdO1xuICB9IGVsc2Uge1xuICAgIC8vIG90aGVyd2lzZSwgY29weSB0aGUgbW9kZWwgZGF0YSB0byB0aGUgV0FTTSBoZWFwLlxuICAgIFttb2RlbERhdGFPZmZzZXQsIG1vZGVsRGF0YUxlbmd0aF0gPSBjb3B5RnJvbUV4dGVybmFsQnVmZmVyKG1vZGVsRGF0YSk7XG4gIH1cblxuICBsZXQgc2Vzc2lvbkhhbmRsZSA9IDA7XG4gIGxldCBzZXNzaW9uT3B0aW9uc0hhbmRsZSA9IDA7XG4gIGxldCBpb0JpbmRpbmdIYW5kbGUgPSAwO1xuICBsZXQgYWxsb2NzOiBudW1iZXJbXSA9IFtdO1xuICBjb25zdCBpbnB1dE5hbWVzVVRGOEVuY29kZWQgPSBbXTtcbiAgY29uc3Qgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZCA9IFtdO1xuXG4gIHRyeSB7XG4gICAgW3Nlc3Npb25PcHRpb25zSGFuZGxlLCBhbGxvY3NdID0gYXdhaXQgc2V0U2Vzc2lvbk9wdGlvbnMob3B0aW9ucyk7XG5cbiAgICBpZiAob3B0aW9ucz8uZXh0ZXJuYWxEYXRhICYmIHdhc20ubW91bnRFeHRlcm5hbERhdGEpIHtcbiAgICAgIGNvbnN0IGxvYWRpbmdQcm9taXNlcyA9IFtdO1xuICAgICAgZm9yIChjb25zdCBmaWxlIG9mIG9wdGlvbnMuZXh0ZXJuYWxEYXRhKSB7XG4gICAgICAgIGNvbnN0IHBhdGggPSB0eXBlb2YgZmlsZSA9PT0gJ3N0cmluZycgPyBmaWxlIDogZmlsZS5wYXRoO1xuICAgICAgICBsb2FkaW5nUHJvbWlzZXMucHVzaChcbiAgICAgICAgICBsb2FkRmlsZSh0eXBlb2YgZmlsZSA9PT0gJ3N0cmluZycgPyBmaWxlIDogZmlsZS5kYXRhKS50aGVuKChkYXRhKSA9PiB7XG4gICAgICAgICAgICB3YXNtLm1vdW50RXh0ZXJuYWxEYXRhKHBhdGgsIGRhdGEpO1xuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICAvLyB3YWl0IGZvciBhbGwgZXh0ZXJuYWwgZGF0YSBmaWxlcyB0byBiZSBsb2FkZWRcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKGxvYWRpbmdQcm9taXNlcyk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBwcm92aWRlciBvZiBvcHRpb25zPy5leGVjdXRpb25Qcm92aWRlcnMgPz8gW10pIHtcbiAgICAgIGNvbnN0IHByb3ZpZGVyTmFtZSA9IHR5cGVvZiBwcm92aWRlciA9PT0gJ3N0cmluZycgPyBwcm92aWRlciA6IHByb3ZpZGVyLm5hbWU7XG4gICAgICBpZiAocHJvdmlkZXJOYW1lID09PSAnd2Vibm4nKSB7XG4gICAgICAgIHdhc20uc2hvdWxkVHJhbnNmZXJUb01MVGVuc29yID0gZmFsc2U7XG4gICAgICAgIGlmICh0eXBlb2YgcHJvdmlkZXIgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgY29uc3Qgd2Vibm5PcHRpb25zID0gcHJvdmlkZXIgYXMgSW5mZXJlbmNlU2Vzc2lvbi5XZWJOTkV4ZWN1dGlvblByb3ZpZGVyT3B0aW9uO1xuICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSAod2Vibm5PcHRpb25zIGFzIEluZmVyZW5jZVNlc3Npb24uV2ViTk5PcHRpb25zV2l0aE1MQ29udGV4dCk/LmNvbnRleHQ7XG4gICAgICAgICAgY29uc3QgZ3B1RGV2aWNlID0gKHdlYm5uT3B0aW9ucyBhcyBJbmZlcmVuY2VTZXNzaW9uLldlYk5OT3B0aW9uc1dlYkdwdSk/LmdwdURldmljZTtcbiAgICAgICAgICBjb25zdCBkZXZpY2VUeXBlID0gKHdlYm5uT3B0aW9ucyBhcyBJbmZlcmVuY2VTZXNzaW9uLldlYk5OQ29udGV4dE9wdGlvbnMpPy5kZXZpY2VUeXBlO1xuICAgICAgICAgIGNvbnN0IHBvd2VyUHJlZmVyZW5jZSA9ICh3ZWJubk9wdGlvbnMgYXMgSW5mZXJlbmNlU2Vzc2lvbi5XZWJOTkNvbnRleHRPcHRpb25zKT8ucG93ZXJQcmVmZXJlbmNlO1xuICAgICAgICAgIGlmIChjb250ZXh0KSB7XG4gICAgICAgICAgICB3YXNtLmN1cnJlbnRDb250ZXh0ID0gY29udGV4dCBhcyBNTENvbnRleHQ7XG4gICAgICAgICAgfSBlbHNlIGlmIChncHVEZXZpY2UpIHtcbiAgICAgICAgICAgIHdhc20uY3VycmVudENvbnRleHQgPSBhd2FpdCB3YXNtLndlYm5uQ3JlYXRlTUxDb250ZXh0IShncHVEZXZpY2UpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB3YXNtLmN1cnJlbnRDb250ZXh0ID0gYXdhaXQgd2FzbS53ZWJubkNyZWF0ZU1MQ29udGV4dCEoeyBkZXZpY2VUeXBlLCBwb3dlclByZWZlcmVuY2UgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHdhc20uY3VycmVudENvbnRleHQgPSBhd2FpdCB3YXNtLndlYm5uQ3JlYXRlTUxDb250ZXh0ISgpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHNlc3Npb25IYW5kbGUgPSBhd2FpdCB3YXNtLl9PcnRDcmVhdGVTZXNzaW9uKG1vZGVsRGF0YU9mZnNldCwgbW9kZWxEYXRhTGVuZ3RoLCBzZXNzaW9uT3B0aW9uc0hhbmRsZSk7XG4gICAgd2FzbS53ZWJncHVPbkNyZWF0ZVNlc3Npb24/LihzZXNzaW9uSGFuZGxlKTtcbiAgICBpZiAoc2Vzc2lvbkhhbmRsZSA9PT0gMCkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBjcmVhdGUgYSBzZXNzaW9uLlwiKTtcbiAgICB9XG5cbiAgICB3YXNtLmpzZXBPbkNyZWF0ZVNlc3Npb24/LigpO1xuXG4gICAgLy8gY2xlYXIgY3VycmVudCBNTENvbnRleHQgYWZ0ZXIgc2Vzc2lvbiBjcmVhdGlvblxuICAgIGlmICh3YXNtLmN1cnJlbnRDb250ZXh0KSB7XG4gICAgICB3YXNtLndlYm5uUmVnaXN0ZXJNTENvbnRleHQhKHNlc3Npb25IYW5kbGUsIHdhc20uY3VycmVudENvbnRleHQpO1xuICAgICAgd2FzbS5jdXJyZW50Q29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgIHdhc20uc2hvdWxkVHJhbnNmZXJUb01MVGVuc29yID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBjb25zdCBbaW5wdXRDb3VudCwgb3V0cHV0Q291bnRdID0gZ2V0U2Vzc2lvbklucHV0T3V0cHV0Q291bnQoc2Vzc2lvbkhhbmRsZSk7XG5cbiAgICBjb25zdCBlbmFibGVHcmFwaENhcHR1cmUgPSAhIW9wdGlvbnM/LmVuYWJsZUdyYXBoQ2FwdHVyZTtcblxuICAgIGNvbnN0IGlucHV0TmFtZXMgPSBbXTtcbiAgICBjb25zdCBvdXRwdXROYW1lcyA9IFtdO1xuICAgIGNvbnN0IGlucHV0TWV0YWRhdGE6IEluZmVyZW5jZVNlc3Npb24uVmFsdWVNZXRhZGF0YVtdID0gW107XG4gICAgY29uc3Qgb3V0cHV0TWV0YWRhdGE6IEluZmVyZW5jZVNlc3Npb24uVmFsdWVNZXRhZGF0YVtdID0gW107XG4gICAgY29uc3Qgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zOiBTdXBwb3J0ZWRUZW5zb3JEYXRhTG9jYXRpb25Gb3JJbnB1dE91dHB1dFtdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENvdW50OyBpKyspIHtcbiAgICAgIGNvbnN0IFtuYW1lT2Zmc2V0LCBlbGVtZW50VHlwZSwgc2hhcGVdID0gZ2V0U2Vzc2lvbklucHV0T3V0cHV0TWV0YWRhdGEoc2Vzc2lvbkhhbmRsZSwgaSk7XG4gICAgICBpZiAobmFtZU9mZnNldCA9PT0gMCkge1xuICAgICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IGdldCBhbiBpbnB1dCBuYW1lLlwiKTtcbiAgICAgIH1cbiAgICAgIGlucHV0TmFtZXNVVEY4RW5jb2RlZC5wdXNoKG5hbWVPZmZzZXQpO1xuICAgICAgY29uc3QgbmFtZSA9IHdhc20uVVRGOFRvU3RyaW5nKG5hbWVPZmZzZXQpO1xuICAgICAgaW5wdXROYW1lcy5wdXNoKG5hbWUpO1xuICAgICAgaW5wdXRNZXRhZGF0YS5wdXNoKFxuICAgICAgICBlbGVtZW50VHlwZSA9PT0gMFxuICAgICAgICAgID8geyBuYW1lLCBpc1RlbnNvcjogZmFsc2UgfVxuICAgICAgICAgIDogeyBuYW1lLCBpc1RlbnNvcjogdHJ1ZSwgdHlwZTogdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcoZWxlbWVudFR5cGUpLCBzaGFwZTogc2hhcGUhIH0sXG4gICAgICApO1xuICAgIH1cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG91dHB1dENvdW50OyBpKyspIHtcbiAgICAgIGNvbnN0IFtuYW1lT2Zmc2V0LCBlbGVtZW50VHlwZSwgc2hhcGVdID0gZ2V0U2Vzc2lvbklucHV0T3V0cHV0TWV0YWRhdGEoc2Vzc2lvbkhhbmRsZSwgaSArIGlucHV0Q291bnQpO1xuICAgICAgaWYgKG5hbWVPZmZzZXQgPT09IDApIHtcbiAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBnZXQgYW4gb3V0cHV0IG5hbWUuXCIpO1xuICAgICAgfVxuICAgICAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZC5wdXNoKG5hbWVPZmZzZXQpO1xuICAgICAgY29uc3QgbmFtZVN0cmluZyA9IHdhc20uVVRGOFRvU3RyaW5nKG5hbWVPZmZzZXQpO1xuICAgICAgb3V0cHV0TmFtZXMucHVzaChuYW1lU3RyaW5nKTtcbiAgICAgIG91dHB1dE1ldGFkYXRhLnB1c2goXG4gICAgICAgIGVsZW1lbnRUeXBlID09PSAwXG4gICAgICAgICAgPyB7IG5hbWU6IG5hbWVTdHJpbmcsIGlzVGVuc29yOiBmYWxzZSB9XG4gICAgICAgICAgOiB7IG5hbWU6IG5hbWVTdHJpbmcsIGlzVGVuc29yOiB0cnVlLCB0eXBlOiB0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyhlbGVtZW50VHlwZSksIHNoYXBlOiBzaGFwZSEgfSxcbiAgICAgICk7XG5cbiAgICAgIGlmICghQlVJTERfREVGUy5ESVNBQkxFX0pTRVApIHtcbiAgICAgICAgaWYgKGVuYWJsZUdyYXBoQ2FwdHVyZSAmJiBvcHRpb25zPy5wcmVmZXJyZWRPdXRwdXRMb2NhdGlvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zLnB1c2goJ2dwdS1idWZmZXInKTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBsb2NhdGlvbiA9XG4gICAgICAgICAgdHlwZW9mIG9wdGlvbnM/LnByZWZlcnJlZE91dHB1dExvY2F0aW9uID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgPyBvcHRpb25zLnByZWZlcnJlZE91dHB1dExvY2F0aW9uXG4gICAgICAgICAgICA6IChvcHRpb25zPy5wcmVmZXJyZWRPdXRwdXRMb2NhdGlvbj8uW25hbWVTdHJpbmddID8/ICdjcHUnKTtcbiAgICAgICAgY29uc3QgaXNHcmFwaE91dHB1dCA9IHdhc20ud2Vibm5Jc0dyYXBoT3V0cHV0O1xuICAgICAgICBpZiAobG9jYXRpb24gPT09ICdjcHUnICYmIGlzR3JhcGhPdXRwdXQgJiYgaXNHcmFwaE91dHB1dChzZXNzaW9uSGFuZGxlLCBuYW1lU3RyaW5nKSkge1xuICAgICAgICAgIG91dHB1dFByZWZlcnJlZExvY2F0aW9ucy5wdXNoKCdtbC10ZW5zb3ItY3B1LW91dHB1dCcpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsb2NhdGlvbiAhPT0gJ2NwdScgJiYgbG9jYXRpb24gIT09ICdjcHUtcGlubmVkJyAmJiBsb2NhdGlvbiAhPT0gJ2dwdS1idWZmZXInICYmIGxvY2F0aW9uICE9PSAnbWwtdGVuc29yJykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgTm90IHN1cHBvcnRlZCBwcmVmZXJyZWQgb3V0cHV0IGxvY2F0aW9uOiAke2xvY2F0aW9ufS5gKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZW5hYmxlR3JhcGhDYXB0dXJlICYmIGxvY2F0aW9uICE9PSAnZ3B1LWJ1ZmZlcicpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgTm90IHN1cHBvcnRlZCBwcmVmZXJyZWQgb3V0cHV0IGxvY2F0aW9uOiAke2xvY2F0aW9ufS4gT25seSAnZ3B1LWJ1ZmZlcicgbG9jYXRpb24gaXMgc3VwcG9ydGVkIHdoZW4gZW5hYmxlR3JhcGhDYXB0dXJlIGlzIHRydWUuYCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIG91dHB1dFByZWZlcnJlZExvY2F0aW9ucy5wdXNoKGxvY2F0aW9uKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB1c2UgSU8gYmluZGluZyBvbmx5IHdoZW4gYXQgbGVhc3Qgb25lIG91dHB1dCBpcyBwcmVmZXJyZWQgdG8gYmUgb24gR1BVLlxuICAgIGxldCBiaW5kaW5nU3RhdGU6IElPQmluZGluZ1N0YXRlIHwgbnVsbCA9IG51bGw7XG4gICAgaWYgKFxuICAgICAgIUJVSUxEX0RFRlMuRElTQUJMRV9KU0VQICYmXG4gICAgICBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnMuc29tZSgobCkgPT4gbCA9PT0gJ2dwdS1idWZmZXInIHx8IGwgPT09ICdtbC10ZW5zb3InIHx8IGwgPT09ICdtbC10ZW5zb3ItY3B1LW91dHB1dCcpXG4gICAgKSB7XG4gICAgICBpb0JpbmRpbmdIYW5kbGUgPSB3YXNtLl9PcnRDcmVhdGVCaW5kaW5nKHNlc3Npb25IYW5kbGUpO1xuICAgICAgaWYgKGlvQmluZGluZ0hhbmRsZSA9PT0gMCkge1xuICAgICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IGNyZWF0ZSBJTyBiaW5kaW5nLlwiKTtcbiAgICAgIH1cblxuICAgICAgYmluZGluZ1N0YXRlID0ge1xuICAgICAgICBoYW5kbGU6IGlvQmluZGluZ0hhbmRsZSxcbiAgICAgICAgb3V0cHV0UHJlZmVycmVkTG9jYXRpb25zLFxuICAgICAgICBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnNFbmNvZGVkOiBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnNcbiAgICAgICAgICAvLyAnbWwtdGVuc29yLWNwdS1vdXRwdXQnIGlzIHRyZWF0ZWQgYXMgJ21sLXRlbnNvcicgZm9yIHRoZSBwdXJwb3NlIG9mIElPIGJpbmRpbmcuXG4gICAgICAgICAgLm1hcCgobCkgPT4gKGwgPT09ICdtbC10ZW5zb3ItY3B1LW91dHB1dCcgPyAnbWwtdGVuc29yJyA6IGwpKVxuICAgICAgICAgIC5tYXAoKGwpID0+IGRhdGFMb2NhdGlvblN0cmluZ1RvRW51bShsKSksXG4gICAgICB9O1xuICAgIH1cblxuICAgIGFjdGl2ZVNlc3Npb25zLnNldChzZXNzaW9uSGFuZGxlLCBbXG4gICAgICBzZXNzaW9uSGFuZGxlLFxuICAgICAgaW5wdXROYW1lc1VURjhFbmNvZGVkLFxuICAgICAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZCxcbiAgICAgIGJpbmRpbmdTdGF0ZSxcbiAgICAgIGVuYWJsZUdyYXBoQ2FwdHVyZSxcbiAgICAgIGZhbHNlLFxuICAgIF0pO1xuICAgIHJldHVybiBbc2Vzc2lvbkhhbmRsZSwgaW5wdXROYW1lcywgb3V0cHV0TmFtZXMsIGlucHV0TWV0YWRhdGEsIG91dHB1dE1ldGFkYXRhXTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlucHV0TmFtZXNVVEY4RW5jb2RlZC5mb3JFYWNoKChidWYpID0+IHdhc20uX09ydEZyZWUoYnVmKSk7XG4gICAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZC5mb3JFYWNoKChidWYpID0+IHdhc20uX09ydEZyZWUoYnVmKSk7XG5cbiAgICBpZiAoaW9CaW5kaW5nSGFuZGxlICE9PSAwKSB7XG4gICAgICBpZiAod2FzbS5fT3J0UmVsZWFzZUJpbmRpbmcoaW9CaW5kaW5nSGFuZGxlKSAhPT0gMCkge1xuICAgICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IHJlbGVhc2UgSU8gYmluZGluZy5cIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHNlc3Npb25IYW5kbGUgIT09IDApIHtcbiAgICAgIGlmICh3YXNtLl9PcnRSZWxlYXNlU2Vzc2lvbihzZXNzaW9uSGFuZGxlKSAhPT0gMCkge1xuICAgICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IHJlbGVhc2Ugc2Vzc2lvbi5cIik7XG4gICAgICB9XG4gICAgfVxuICAgIHRocm93IGU7XG4gIH0gZmluYWxseSB7XG4gICAgd2FzbS5fZnJlZShtb2RlbERhdGFPZmZzZXQpO1xuICAgIGlmIChzZXNzaW9uT3B0aW9uc0hhbmRsZSAhPT0gMCkge1xuICAgICAgaWYgKHdhc20uX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucyhzZXNzaW9uT3B0aW9uc0hhbmRsZSkgIT09IDApIHtcbiAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCByZWxlYXNlIHNlc3Npb24gb3B0aW9ucy5cIik7XG4gICAgICB9XG4gICAgfVxuICAgIGFsbG9jcy5mb3JFYWNoKChhbGxvYykgPT4gd2FzbS5fZnJlZShhbGxvYykpO1xuXG4gICAgLy8gdW5tb3VudCBleHRlcm5hbCBkYXRhIGlmIG5lY2Vzc2FyeVxuICAgIHdhc20udW5tb3VudEV4dGVybmFsRGF0YT8uKCk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCByZWxlYXNlU2Vzc2lvbiA9IChzZXNzaW9uSWQ6IG51bWJlcik6IHZvaWQgPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgY29uc3Qgc2Vzc2lvbiA9IGFjdGl2ZVNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xuICBpZiAoIXNlc3Npb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCByZWxlYXNlIHNlc3Npb24uIGludmFsaWQgc2Vzc2lvbiBpZDogJHtzZXNzaW9uSWR9YCk7XG4gIH1cbiAgY29uc3QgW3Nlc3Npb25IYW5kbGUsIGlucHV0TmFtZXNVVEY4RW5jb2RlZCwgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZCwgaW9CaW5kaW5nU3RhdGUsIGVuYWJsZUdyYXBoQ2FwdHVyZV0gPSBzZXNzaW9uO1xuXG4gIGlmIChpb0JpbmRpbmdTdGF0ZSkge1xuICAgIGlmIChlbmFibGVHcmFwaENhcHR1cmUpIHtcbiAgICAgIGlmICh3YXNtLl9PcnRDbGVhckJvdW5kT3V0cHV0cyhpb0JpbmRpbmdTdGF0ZS5oYW5kbGUpICE9PSAwKSB7XG4gICAgICAgIGNoZWNrTGFzdEVycm9yKFwiQ2FuJ3QgY2xlYXIgYm91bmQgb3V0cHV0cy5cIik7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICh3YXNtLl9PcnRSZWxlYXNlQmluZGluZyhpb0JpbmRpbmdTdGF0ZS5oYW5kbGUpICE9PSAwKSB7XG4gICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IHJlbGVhc2UgSU8gYmluZGluZy5cIik7XG4gICAgfVxuICB9XG5cbiAgd2FzbS5qc2VwT25SZWxlYXNlU2Vzc2lvbj8uKHNlc3Npb25JZCk7XG4gIHdhc20ud2Vibm5PblJlbGVhc2VTZXNzaW9uPy4oc2Vzc2lvbklkKTtcbiAgd2FzbS53ZWJncHVPblJlbGVhc2VTZXNzaW9uPy4oc2Vzc2lvbklkKTtcblxuICBpbnB1dE5hbWVzVVRGOEVuY29kZWQuZm9yRWFjaCgoYnVmKSA9PiB3YXNtLl9PcnRGcmVlKGJ1ZikpO1xuICBvdXRwdXROYW1lc1VURjhFbmNvZGVkLmZvckVhY2goKGJ1ZikgPT4gd2FzbS5fT3J0RnJlZShidWYpKTtcbiAgaWYgKHdhc20uX09ydFJlbGVhc2VTZXNzaW9uKHNlc3Npb25IYW5kbGUpICE9PSAwKSB7XG4gICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCByZWxlYXNlIHNlc3Npb24uXCIpO1xuICB9XG4gIGFjdGl2ZVNlc3Npb25zLmRlbGV0ZShzZXNzaW9uSWQpO1xufTtcblxuZXhwb3J0IGNvbnN0IHByZXBhcmVJbnB1dE91dHB1dFRlbnNvciA9IGFzeW5jIChcbiAgdGVuc29yOiBUZW5zb3JNZXRhZGF0YSB8IG51bGwsXG4gIHRlbnNvckhhbmRsZXM6IG51bWJlcltdLFxuICBhbGxvY3M6IG51bWJlcltdLFxuICBzZXNzaW9uSWQ6IG51bWJlcixcbiAgdGVuc29yTmFtZVVURjhFbmNvZGVkOiBudW1iZXIsXG4gIGluZGV4OiBudW1iZXIsXG4gIGVuYWJsZUdyYXBoQ2FwdHVyZSA9IGZhbHNlLFxuKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGlmICghdGVuc29yKSB7XG4gICAgdGVuc29ySGFuZGxlcy5wdXNoKDApO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICBjb25zdCBwdHJTaXplID0gd2FzbS5QVFJfU0laRTtcblxuICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclswXTtcbiAgY29uc3QgZGltcyA9IHRlbnNvclsxXTtcbiAgY29uc3QgbG9jYXRpb24gPSB0ZW5zb3JbM107XG4gIGxldCBhY3R1YWxMb2NhdGlvbiA9IGxvY2F0aW9uO1xuXG4gIGxldCByYXdEYXRhOiBudW1iZXI7XG4gIGxldCBkYXRhQnl0ZUxlbmd0aDogbnVtYmVyO1xuXG4gIGlmIChkYXRhVHlwZSA9PT0gJ3N0cmluZycgJiYgKGxvY2F0aW9uID09PSAnZ3B1LWJ1ZmZlcicgfHwgbG9jYXRpb24gPT09ICdtbC10ZW5zb3InKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignU3RyaW5nIHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkIG9uIEdQVS4nKTtcbiAgfVxuXG4gIGlmIChlbmFibGVHcmFwaENhcHR1cmUgJiYgbG9jYXRpb24gIT09ICdncHUtYnVmZmVyJykge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBFeHRlcm5hbCBidWZmZXIgbXVzdCBiZSBwcm92aWRlZCBmb3IgaW5wdXQvb3V0cHV0IGluZGV4ICR7aW5kZXh9IHdoZW4gZW5hYmxlR3JhcGhDYXB0dXJlIGlzIHRydWUuYCxcbiAgICApO1xuICB9XG5cbiAgaWYgKGxvY2F0aW9uID09PSAnZ3B1LWJ1ZmZlcicpIHtcbiAgICBjb25zdCBncHVCdWZmZXIgPSB0ZW5zb3JbMl0uZ3B1QnVmZmVyO1xuICAgIGRhdGFCeXRlTGVuZ3RoID0gY2FsY3VsYXRlVGVuc29yU2l6ZUluQnl0ZXModGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0oZGF0YVR5cGUpLCBkaW1zKSE7XG5cbiAgICBpZiAoQlVJTERfREVGUy5VU0VfV0VCR1BVX0VQKSB7XG4gICAgICBjb25zdCByZWdpc3RlckJ1ZmZlciA9IHdhc20ud2ViZ3B1UmVnaXN0ZXJCdWZmZXI7XG4gICAgICBpZiAoIXJlZ2lzdGVyQnVmZmVyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVGVuc29yIGxvY2F0aW9uIFwiZ3B1LWJ1ZmZlclwiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJHUFUuJyk7XG4gICAgICB9XG5cbiAgICAgIHJhd0RhdGEgPSByZWdpc3RlckJ1ZmZlcihncHVCdWZmZXIsIHNlc3Npb25JZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHJlZ2lzdGVyQnVmZmVyID0gd2FzbS5qc2VwUmVnaXN0ZXJCdWZmZXI7XG4gICAgICBpZiAoIXJlZ2lzdGVyQnVmZmVyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVGVuc29yIGxvY2F0aW9uIFwiZ3B1LWJ1ZmZlclwiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJHUFUuJyk7XG4gICAgICB9XG4gICAgICByYXdEYXRhID0gcmVnaXN0ZXJCdWZmZXIoc2Vzc2lvbklkLCBpbmRleCwgZ3B1QnVmZmVyLCBkYXRhQnl0ZUxlbmd0aCk7XG4gICAgfVxuICB9IGVsc2UgaWYgKGxvY2F0aW9uID09PSAnbWwtdGVuc29yJykge1xuICAgIGNvbnN0IG1sVGVuc29yID0gdGVuc29yWzJdLm1sVGVuc29yIGFzIE1MVGVuc29yO1xuICAgIGRhdGFCeXRlTGVuZ3RoID0gY2FsY3VsYXRlVGVuc29yU2l6ZUluQnl0ZXModGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0oZGF0YVR5cGUpLCBkaW1zKSE7XG5cbiAgICBjb25zdCByZWdpc3Rlck1MVGVuc29yID0gd2FzbS53ZWJublJlZ2lzdGVyTUxUZW5zb3I7XG4gICAgaWYgKCFyZWdpc3Rlck1MVGVuc29yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBsb2NhdGlvbiBcIm1sLXRlbnNvclwiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJOTi4nKTtcbiAgICB9XG4gICAgcmF3RGF0YSA9IHJlZ2lzdGVyTUxUZW5zb3Ioc2Vzc2lvbklkLCBtbFRlbnNvciwgdGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0oZGF0YVR5cGUpLCBkaW1zKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBkYXRhID0gdGVuc29yWzJdO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgIC8vIHN0cmluZyB0ZW5zb3JcbiAgICAgIGRhdGFCeXRlTGVuZ3RoID0gcHRyU2l6ZSAqIGRhdGEubGVuZ3RoO1xuICAgICAgcmF3RGF0YSA9IHdhc20uX21hbGxvYyhkYXRhQnl0ZUxlbmd0aCk7XG4gICAgICBhbGxvY3MucHVzaChyYXdEYXRhKTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodHlwZW9mIGRhdGFbaV0gIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgdGVuc29yIGRhdGEgYXQgaW5kZXggJHtpfSBpcyBub3QgYSBzdHJpbmdgKTtcbiAgICAgICAgfVxuICAgICAgICB3YXNtLnNldFZhbHVlKHJhd0RhdGEgKyBpICogcHRyU2l6ZSwgYWxsb2NXYXNtU3RyaW5nKGRhdGFbaV0sIGFsbG9jcyksICcqJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGlzR3JhcGhJbnB1dCA9IHdhc20ud2Vibm5Jc0dyYXBoSW5wdXQ7XG4gICAgICBjb25zdCBpc0dyYXBoT3V0cHV0ID0gd2FzbS53ZWJubklzR3JhcGhPdXRwdXQ7XG4gICAgICBpZiAoZGF0YVR5cGUgIT09ICdzdHJpbmcnICYmIGlzR3JhcGhJbnB1dCAmJiBpc0dyYXBoT3V0cHV0KSB7XG4gICAgICAgIGNvbnN0IHRlbnNvck5hbWUgPSB3YXNtLlVURjhUb1N0cmluZyh0ZW5zb3JOYW1lVVRGOEVuY29kZWQpO1xuICAgICAgICAvLyBQcm9tb3RlIHRoZSB0ZW5zb3IgdG8gJ21sLXRlbnNvcicgaWYgaXQgaXMgYSBncmFwaCBpbnB1dC5cbiAgICAgICAgaWYgKGlzR3JhcGhJbnB1dChzZXNzaW9uSWQsIHRlbnNvck5hbWUpIHx8IGlzR3JhcGhPdXRwdXQoc2Vzc2lvbklkLCB0ZW5zb3JOYW1lKSkge1xuICAgICAgICAgIGNvbnN0IGRhdGFUeXBlRW51bSA9IHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtKGRhdGFUeXBlKTtcbiAgICAgICAgICBkYXRhQnl0ZUxlbmd0aCA9IGNhbGN1bGF0ZVRlbnNvclNpemVJbkJ5dGVzKGRhdGFUeXBlRW51bSwgZGltcykhO1xuICAgICAgICAgIGFjdHVhbExvY2F0aW9uID0gJ21sLXRlbnNvcic7XG4gICAgICAgICAgY29uc3QgY3JlYXRlVGVtcG9yYXJ5VGVuc29yID0gd2FzbS53ZWJubkNyZWF0ZVRlbXBvcmFyeVRlbnNvcjtcbiAgICAgICAgICBjb25zdCB1cGxvYWRUZW5zb3IgPSB3YXNtLndlYm5uVXBsb2FkVGVuc29yO1xuICAgICAgICAgIGlmICghY3JlYXRlVGVtcG9yYXJ5VGVuc29yIHx8ICF1cGxvYWRUZW5zb3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGVuc29yIGxvY2F0aW9uIFwibWwtdGVuc29yXCIgaXMgbm90IHN1cHBvcnRlZCB3aXRob3V0IHVzaW5nIFdlYk5OLicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCB0ZW5zb3JJZCA9IGF3YWl0IGNyZWF0ZVRlbXBvcmFyeVRlbnNvcihzZXNzaW9uSWQsIGRhdGFUeXBlRW51bSwgZGltcyBhcyBudW1iZXJbXSk7XG4gICAgICAgICAgdXBsb2FkVGVuc29yKHRlbnNvcklkLCBuZXcgVWludDhBcnJheShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBkYXRhLmJ5dGVMZW5ndGgpKTtcbiAgICAgICAgICByYXdEYXRhID0gdGVuc29ySWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGF0YUJ5dGVMZW5ndGggPSBkYXRhLmJ5dGVMZW5ndGg7XG4gICAgICAgICAgcmF3RGF0YSA9IHdhc20uX21hbGxvYyhkYXRhQnl0ZUxlbmd0aCk7XG4gICAgICAgICAgYWxsb2NzLnB1c2gocmF3RGF0YSk7XG4gICAgICAgICAgd2FzbS5IRUFQVTguc2V0KG5ldyBVaW50OEFycmF5KGRhdGEuYnVmZmVyLCBkYXRhLmJ5dGVPZmZzZXQsIGRhdGFCeXRlTGVuZ3RoKSwgcmF3RGF0YSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRhdGFCeXRlTGVuZ3RoID0gZGF0YS5ieXRlTGVuZ3RoO1xuICAgICAgICByYXdEYXRhID0gd2FzbS5fbWFsbG9jKGRhdGFCeXRlTGVuZ3RoKTtcbiAgICAgICAgYWxsb2NzLnB1c2gocmF3RGF0YSk7XG4gICAgICAgIHdhc20uSEVBUFU4LnNldChuZXcgVWludDhBcnJheShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBkYXRhQnl0ZUxlbmd0aCksIHJhd0RhdGEpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHN0YWNrID0gd2FzbS5zdGFja1NhdmUoKTtcbiAgY29uc3QgZGltc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyg0ICogZGltcy5sZW5ndGgpO1xuICB0cnkge1xuICAgIGRpbXMuZm9yRWFjaCgoZCwgaW5kZXgpID0+IHdhc20uc2V0VmFsdWUoZGltc09mZnNldCArIGluZGV4ICogcHRyU2l6ZSwgZCwgcHRyU2l6ZSA9PT0gNCA/ICdpMzInIDogJ2k2NCcpKTtcbiAgICBjb25zdCB0ZW5zb3IgPSB3YXNtLl9PcnRDcmVhdGVUZW5zb3IoXG4gICAgICB0ZW5zb3JEYXRhVHlwZVN0cmluZ1RvRW51bShkYXRhVHlwZSksXG4gICAgICByYXdEYXRhLFxuICAgICAgZGF0YUJ5dGVMZW5ndGgsXG4gICAgICBkaW1zT2Zmc2V0LFxuICAgICAgZGltcy5sZW5ndGgsXG4gICAgICBkYXRhTG9jYXRpb25TdHJpbmdUb0VudW0oYWN0dWFsTG9jYXRpb24pLFxuICAgICk7XG4gICAgaWYgKHRlbnNvciA9PT0gMCkge1xuICAgICAgY2hlY2tMYXN0RXJyb3IoYENhbid0IGNyZWF0ZSB0ZW5zb3IgZm9yIGlucHV0L291dHB1dC4gc2Vzc2lvbj0ke3Nlc3Npb25JZH0sIGluZGV4PSR7aW5kZXh9LmApO1xuICAgIH1cbiAgICB0ZW5zb3JIYW5kbGVzLnB1c2godGVuc29yKTtcbiAgfSBmaW5hbGx5IHtcbiAgICB3YXNtLnN0YWNrUmVzdG9yZShzdGFjayk7XG4gIH1cbn07XG5cbi8qKlxuICogcGVyZm9ybSBpbmZlcmVuY2UgcnVuXG4gKi9cbmV4cG9ydCBjb25zdCBydW4gPSBhc3luYyAoXG4gIHNlc3Npb25JZDogbnVtYmVyLFxuICBpbnB1dEluZGljZXM6IG51bWJlcltdLFxuICBpbnB1dFRlbnNvcnM6IFRlbnNvck1ldGFkYXRhW10sXG4gIG91dHB1dEluZGljZXM6IG51bWJlcltdLFxuICBvdXRwdXRUZW5zb3JzOiBBcnJheTxUZW5zb3JNZXRhZGF0YSB8IG51bGw+LFxuICBvcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMsXG4pOiBQcm9taXNlPFRlbnNvck1ldGFkYXRhW10+ID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gIGNvbnN0IHB0clNpemUgPSB3YXNtLlBUUl9TSVpFO1xuICBjb25zdCBzZXNzaW9uID0gYWN0aXZlU2Vzc2lvbnMuZ2V0KHNlc3Npb25JZCk7XG4gIGlmICghc2Vzc2lvbikge1xuICAgIHRocm93IG5ldyBFcnJvcihgY2Fubm90IHJ1biBpbmZlcmVuY2UuIGludmFsaWQgc2Vzc2lvbiBpZDogJHtzZXNzaW9uSWR9YCk7XG4gIH1cbiAgY29uc3Qgc2Vzc2lvbkhhbmRsZSA9IHNlc3Npb25bMF07XG4gIGNvbnN0IGlucHV0TmFtZXNVVEY4RW5jb2RlZCA9IHNlc3Npb25bMV07XG4gIGNvbnN0IG91dHB1dE5hbWVzVVRGOEVuY29kZWQgPSBzZXNzaW9uWzJdO1xuICBjb25zdCBpb0JpbmRpbmdTdGF0ZSA9IHNlc3Npb25bM107XG4gIGNvbnN0IGVuYWJsZUdyYXBoQ2FwdHVyZSA9IHNlc3Npb25bNF07XG4gIGNvbnN0IGlucHV0T3V0cHV0Qm91bmQgPSBzZXNzaW9uWzVdO1xuXG4gIGNvbnN0IGlucHV0Q291bnQgPSBpbnB1dEluZGljZXMubGVuZ3RoO1xuICBjb25zdCBvdXRwdXRDb3VudCA9IG91dHB1dEluZGljZXMubGVuZ3RoO1xuXG4gIGxldCBydW5PcHRpb25zSGFuZGxlID0gMDtcbiAgbGV0IHJ1bk9wdGlvbnNBbGxvY3M6IG51bWJlcltdID0gW107XG5cbiAgY29uc3QgaW5wdXRUZW5zb3JIYW5kbGVzOiBudW1iZXJbXSA9IFtdO1xuICBjb25zdCBvdXRwdXRUZW5zb3JIYW5kbGVzOiBudW1iZXJbXSA9IFtdO1xuICBjb25zdCBpbnB1dE91dHB1dEFsbG9jczogbnVtYmVyW10gPSBbXTtcblxuICBjb25zdCBiZWZvcmVSdW5TdGFjayA9IHdhc20uc3RhY2tTYXZlKCk7XG4gIGNvbnN0IGlucHV0VmFsdWVzT2Zmc2V0ID0gd2FzbS5zdGFja0FsbG9jKGlucHV0Q291bnQgKiBwdHJTaXplKTtcbiAgY29uc3QgaW5wdXROYW1lc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyhpbnB1dENvdW50ICogcHRyU2l6ZSk7XG4gIGNvbnN0IG91dHB1dFZhbHVlc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyhvdXRwdXRDb3VudCAqIHB0clNpemUpO1xuICBjb25zdCBvdXRwdXROYW1lc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyhvdXRwdXRDb3VudCAqIHB0clNpemUpO1xuXG4gIHRyeSB7XG4gICAgW3J1bk9wdGlvbnNIYW5kbGUsIHJ1bk9wdGlvbnNBbGxvY3NdID0gc2V0UnVuT3B0aW9ucyhvcHRpb25zKTtcblxuICAgIC8vIGNyZWF0ZSBpbnB1dCB0ZW5zb3JzXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENvdW50OyBpKyspIHtcbiAgICAgIGF3YWl0IHByZXBhcmVJbnB1dE91dHB1dFRlbnNvcihcbiAgICAgICAgaW5wdXRUZW5zb3JzW2ldLFxuICAgICAgICBpbnB1dFRlbnNvckhhbmRsZXMsXG4gICAgICAgIGlucHV0T3V0cHV0QWxsb2NzLFxuICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgIGlucHV0TmFtZXNVVEY4RW5jb2RlZFtpbnB1dEluZGljZXNbaV1dLFxuICAgICAgICBpbnB1dEluZGljZXNbaV0sXG4gICAgICAgIGVuYWJsZUdyYXBoQ2FwdHVyZSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIG91dHB1dCB0ZW5zb3JzXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRDb3VudDsgaSsrKSB7XG4gICAgICBhd2FpdCBwcmVwYXJlSW5wdXRPdXRwdXRUZW5zb3IoXG4gICAgICAgIG91dHB1dFRlbnNvcnNbaV0sXG4gICAgICAgIG91dHB1dFRlbnNvckhhbmRsZXMsXG4gICAgICAgIGlucHV0T3V0cHV0QWxsb2NzLFxuICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgIG91dHB1dE5hbWVzVVRGOEVuY29kZWRbb3V0cHV0SW5kaWNlc1tpXV0sXG4gICAgICAgIGlucHV0Q291bnQgKyBvdXRwdXRJbmRpY2VzW2ldLFxuICAgICAgICBlbmFibGVHcmFwaENhcHR1cmUsXG4gICAgICApO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRDb3VudDsgaSsrKSB7XG4gICAgICB3YXNtLnNldFZhbHVlKGlucHV0VmFsdWVzT2Zmc2V0ICsgaSAqIHB0clNpemUsIGlucHV0VGVuc29ySGFuZGxlc1tpXSwgJyonKTtcbiAgICAgIHdhc20uc2V0VmFsdWUoaW5wdXROYW1lc09mZnNldCArIGkgKiBwdHJTaXplLCBpbnB1dE5hbWVzVVRGOEVuY29kZWRbaW5wdXRJbmRpY2VzW2ldXSwgJyonKTtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRDb3VudDsgaSsrKSB7XG4gICAgICB3YXNtLnNldFZhbHVlKG91dHB1dFZhbHVlc09mZnNldCArIGkgKiBwdHJTaXplLCBvdXRwdXRUZW5zb3JIYW5kbGVzW2ldLCAnKicpO1xuICAgICAgd2FzbS5zZXRWYWx1ZShvdXRwdXROYW1lc09mZnNldCArIGkgKiBwdHJTaXplLCBvdXRwdXROYW1lc1VURjhFbmNvZGVkW291dHB1dEluZGljZXNbaV1dLCAnKicpO1xuICAgIH1cblxuICAgIGlmICghQlVJTERfREVGUy5ESVNBQkxFX0pTRVAgJiYgaW9CaW5kaW5nU3RhdGUgJiYgIWlucHV0T3V0cHV0Qm91bmQpIHtcbiAgICAgIGNvbnN0IHsgaGFuZGxlLCBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnMsIG91dHB1dFByZWZlcnJlZExvY2F0aW9uc0VuY29kZWQgfSA9IGlvQmluZGluZ1N0YXRlO1xuXG4gICAgICBpZiAoaW5wdXROYW1lc1VURjhFbmNvZGVkLmxlbmd0aCAhPT0gaW5wdXRDb3VudCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYGlucHV0IGNvdW50IGZyb20gZmVlZHMgKCR7aW5wdXRDb3VudH0pIGlzIGV4cGVjdGVkIHRvIGJlIGFsd2F5cyBlcXVhbCB0byBtb2RlbCdzIGlucHV0IGNvdW50ICgke2lucHV0TmFtZXNVVEY4RW5jb2RlZC5sZW5ndGh9KS5gLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICAvLyBwcm9jZXNzIGlucHV0c1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENvdW50OyBpKyspIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSBpbnB1dEluZGljZXNbaV07XG4gICAgICAgIGNvbnN0IGVycm9yQ29kZSA9IGF3YWl0IHdhc20uX09ydEJpbmRJbnB1dChoYW5kbGUsIGlucHV0TmFtZXNVVEY4RW5jb2RlZFtpbmRleF0sIGlucHV0VGVuc29ySGFuZGxlc1tpXSk7XG4gICAgICAgIGlmIChlcnJvckNvZGUgIT09IDApIHtcbiAgICAgICAgICBjaGVja0xhc3RFcnJvcihgQ2FuJ3QgYmluZCBpbnB1dFske2l9XSBmb3Igc2Vzc2lvbj0ke3Nlc3Npb25JZH0uYCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gcHJvY2VzcyBwcmUtYWxsb2NhdGVkIG91dHB1dHNcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0Q291bnQ7IGkrKykge1xuICAgICAgICBjb25zdCBpbmRleCA9IG91dHB1dEluZGljZXNbaV07XG4gICAgICAgIGNvbnN0IGxvY2F0aW9uID0gb3V0cHV0VGVuc29yc1tpXT8uWzNdOyAvLyB1bmRlZmluZWQgbWVhbnMgb3V0cHV0IGlzIG5vdCBwcmUtYWxsb2NhdGVkLlxuXG4gICAgICAgIGlmIChsb2NhdGlvbikge1xuICAgICAgICAgIC8vIG91dHB1dCBpcyBwcmUtYWxsb2NhdGVkLiBiaW5kIHRoZSB0ZW5zb3IuXG4gICAgICAgICAgY29uc3QgZXJyb3JDb2RlID0gd2FzbS5fT3J0QmluZE91dHB1dChoYW5kbGUsIG91dHB1dE5hbWVzVVRGOEVuY29kZWRbaW5kZXhdLCBvdXRwdXRUZW5zb3JIYW5kbGVzW2ldLCAwKTtcbiAgICAgICAgICBpZiAoZXJyb3JDb2RlICE9PSAwKSB7XG4gICAgICAgICAgICBjaGVja0xhc3RFcnJvcihgQ2FuJ3QgYmluZCBwcmUtYWxsb2NhdGVkIG91dHB1dFske2l9XSBmb3Igc2Vzc2lvbj0ke3Nlc3Npb25JZH0uYCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIG91dHB1dCBpcyBub3QgcHJlLWFsbG9jYXRlZC4gcmVzZXQgcHJlZmVycmVkIGxvY2F0aW9uLlxuICAgICAgICAgIGNvbnN0IGVycm9yQ29kZSA9IHdhc20uX09ydEJpbmRPdXRwdXQoXG4gICAgICAgICAgICBoYW5kbGUsXG4gICAgICAgICAgICBvdXRwdXROYW1lc1VURjhFbmNvZGVkW2luZGV4XSxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICBvdXRwdXRQcmVmZXJyZWRMb2NhdGlvbnNFbmNvZGVkW2luZGV4XSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChlcnJvckNvZGUgIT09IDApIHtcbiAgICAgICAgICAgIGNoZWNrTGFzdEVycm9yKGBDYW4ndCBiaW5kIG91dHB1dFske2l9XSB0byAke291dHB1dFByZWZlcnJlZExvY2F0aW9uc1tpXX0gZm9yIHNlc3Npb249JHtzZXNzaW9uSWR9LmApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYWN0aXZlU2Vzc2lvbnMuc2V0KHNlc3Npb25JZCwgW1xuICAgICAgICBzZXNzaW9uSGFuZGxlLFxuICAgICAgICBpbnB1dE5hbWVzVVRGOEVuY29kZWQsXG4gICAgICAgIG91dHB1dE5hbWVzVVRGOEVuY29kZWQsXG4gICAgICAgIGlvQmluZGluZ1N0YXRlLFxuICAgICAgICBlbmFibGVHcmFwaENhcHR1cmUsXG4gICAgICAgIHRydWUsXG4gICAgICBdKTtcbiAgICB9XG5cbiAgICB3YXNtLmpzZXBPblJ1blN0YXJ0Py4oc2Vzc2lvbkhhbmRsZSk7XG4gICAgd2FzbS53ZWJubk9uUnVuU3RhcnQ/LihzZXNzaW9uSGFuZGxlKTtcblxuICAgIGxldCBlcnJvckNvZGU6IG51bWJlcjtcbiAgICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9KU0VQICYmIGlvQmluZGluZ1N0YXRlKSB7XG4gICAgICBlcnJvckNvZGUgPSBhd2FpdCB3YXNtLl9PcnRSdW5XaXRoQmluZGluZyhcbiAgICAgICAgc2Vzc2lvbkhhbmRsZSxcbiAgICAgICAgaW9CaW5kaW5nU3RhdGUuaGFuZGxlLFxuICAgICAgICBvdXRwdXRDb3VudCxcbiAgICAgICAgb3V0cHV0VmFsdWVzT2Zmc2V0LFxuICAgICAgICBydW5PcHRpb25zSGFuZGxlLFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZXJyb3JDb2RlID0gYXdhaXQgd2FzbS5fT3J0UnVuKFxuICAgICAgICBzZXNzaW9uSGFuZGxlLFxuICAgICAgICBpbnB1dE5hbWVzT2Zmc2V0LFxuICAgICAgICBpbnB1dFZhbHVlc09mZnNldCxcbiAgICAgICAgaW5wdXRDb3VudCxcbiAgICAgICAgb3V0cHV0TmFtZXNPZmZzZXQsXG4gICAgICAgIG91dHB1dENvdW50LFxuICAgICAgICBvdXRwdXRWYWx1ZXNPZmZzZXQsXG4gICAgICAgIHJ1bk9wdGlvbnNIYW5kbGUsXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChlcnJvckNvZGUgIT09IDApIHtcbiAgICAgIGNoZWNrTGFzdEVycm9yKCdmYWlsZWQgdG8gY2FsbCBPcnRSdW4oKS4nKTtcbiAgICB9XG5cbiAgICBjb25zdCBvdXRwdXQ6IFRlbnNvck1ldGFkYXRhW10gPSBbXTtcbiAgICBjb25zdCBvdXRwdXRQcm9taXNlczogQXJyYXk8UHJvbWlzZTxbbnVtYmVyLCBUZW5zb3IuRGF0YVR5cGVdPj4gPSBbXTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0Q291bnQ7IGkrKykge1xuICAgICAgY29uc3QgdGVuc29yID0gTnVtYmVyKHdhc20uZ2V0VmFsdWUob3V0cHV0VmFsdWVzT2Zmc2V0ICsgaSAqIHB0clNpemUsICcqJykpO1xuICAgICAgaWYgKHRlbnNvciA9PT0gb3V0cHV0VGVuc29ySGFuZGxlc1tpXSkge1xuICAgICAgICAvLyBvdXRwdXQgdGVuc29yIGlzIHByZS1hbGxvY2F0ZWQuIG5vIG5lZWQgdG8gY29weSBkYXRhLlxuICAgICAgICBvdXRwdXQucHVzaChvdXRwdXRUZW5zb3JzW2ldISk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBiZWZvcmVHZXRUZW5zb3JEYXRhU3RhY2sgPSB3YXNtLnN0YWNrU2F2ZSgpO1xuICAgICAgLy8gc3RhY2sgYWxsb2NhdGUgNCBwb2ludGVyIHZhbHVlXG4gICAgICBjb25zdCB0ZW5zb3JEYXRhT2Zmc2V0ID0gd2FzbS5zdGFja0FsbG9jKDQgKiBwdHJTaXplKTtcblxuICAgICAgbGV0IGtlZXBPdXRwdXRUZW5zb3IgPSBmYWxzZTtcbiAgICAgIGxldCB0eXBlOiBUZW5zb3IuVHlwZSB8IHVuZGVmaW5lZCxcbiAgICAgICAgZGF0YU9mZnNldCA9IDA7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBlcnJvckNvZGUgPSB3YXNtLl9PcnRHZXRUZW5zb3JEYXRhKFxuICAgICAgICAgIHRlbnNvcixcbiAgICAgICAgICB0ZW5zb3JEYXRhT2Zmc2V0LFxuICAgICAgICAgIHRlbnNvckRhdGFPZmZzZXQgKyBwdHJTaXplLFxuICAgICAgICAgIHRlbnNvckRhdGFPZmZzZXQgKyAyICogcHRyU2l6ZSxcblxuICAgICAgICAgIHRlbnNvckRhdGFPZmZzZXQgKyAzICogcHRyU2l6ZSxcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGVycm9yQ29kZSAhPT0gMCkge1xuICAgICAgICAgIGNoZWNrTGFzdEVycm9yKGBDYW4ndCBhY2Nlc3Mgb3V0cHV0IHRlbnNvciBkYXRhIG9uIGluZGV4ICR7aX0uYCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdmFsdWVUeXBlID0gcHRyU2l6ZSA9PT0gNCA/ICdpMzInIDogJ2k2NCc7XG4gICAgICAgIGNvbnN0IGRhdGFUeXBlID0gTnVtYmVyKHdhc20uZ2V0VmFsdWUodGVuc29yRGF0YU9mZnNldCwgdmFsdWVUeXBlKSk7XG4gICAgICAgIGRhdGFPZmZzZXQgPSB3YXNtLmdldFZhbHVlKHRlbnNvckRhdGFPZmZzZXQgKyBwdHJTaXplLCAnKicpO1xuICAgICAgICBjb25zdCBkaW1zT2Zmc2V0ID0gd2FzbS5nZXRWYWx1ZSh0ZW5zb3JEYXRhT2Zmc2V0ICsgcHRyU2l6ZSAqIDIsICcqJyk7XG4gICAgICAgIGNvbnN0IGRpbXNMZW5ndGggPSBOdW1iZXIod2FzbS5nZXRWYWx1ZSh0ZW5zb3JEYXRhT2Zmc2V0ICsgcHRyU2l6ZSAqIDMsIHZhbHVlVHlwZSkpO1xuICAgICAgICBjb25zdCBkaW1zID0gW107XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGltc0xlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgZGltcy5wdXNoKE51bWJlcih3YXNtLmdldFZhbHVlKGRpbXNPZmZzZXQgKyBpICogcHRyU2l6ZSwgdmFsdWVUeXBlKSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh3YXNtLl9PcnRGcmVlKGRpbXNPZmZzZXQpICE9PSAwKSB7XG4gICAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBmcmVlIG1lbW9yeSBmb3IgdGVuc29yIGRpbXMuXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNpemUgPSBkaW1zLnJlZHVjZSgoYSwgYikgPT4gYSAqIGIsIDEpO1xuICAgICAgICB0eXBlID0gdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcoZGF0YVR5cGUpO1xuXG4gICAgICAgIGNvbnN0IHByZWZlcnJlZExvY2F0aW9uID0gaW9CaW5kaW5nU3RhdGU/Lm91dHB1dFByZWZlcnJlZExvY2F0aW9uc1tvdXRwdXRJbmRpY2VzW2ldXTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBpZiAocHJlZmVycmVkTG9jYXRpb24gPT09ICdncHUtYnVmZmVyJyB8fCBwcmVmZXJyZWRMb2NhdGlvbiA9PT0gJ21sLXRlbnNvcicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignU3RyaW5nIHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkIG9uIEdQVS4nKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3Qgc3RyaW5nRGF0YTogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gd2FzbS5nZXRWYWx1ZShkYXRhT2Zmc2V0ICsgaSAqIHB0clNpemUsICcqJyk7XG4gICAgICAgICAgICBjb25zdCBuZXh0T2Zmc2V0ID0gd2FzbS5nZXRWYWx1ZShkYXRhT2Zmc2V0ICsgKGkgKyAxKSAqIHB0clNpemUsICcqJyk7XG4gICAgICAgICAgICBjb25zdCBtYXhCeXRlc1RvUmVhZCA9IGkgPT09IHNpemUgLSAxID8gdW5kZWZpbmVkIDogbmV4dE9mZnNldCAtIG9mZnNldDtcbiAgICAgICAgICAgIHN0cmluZ0RhdGEucHVzaCh3YXNtLlVURjhUb1N0cmluZyhvZmZzZXQsIG1heEJ5dGVzVG9SZWFkKSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG91dHB1dC5wdXNoKFt0eXBlLCBkaW1zLCBzdHJpbmdEYXRhLCAnY3B1J10pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIElmIGEgY2VydGFpbiBvdXRwdXQncyBwcmVmZXJyZWQgbG9jYXRpb24gaXMgR1BVIGJ1dCB0aGUgdGVuc29yIGlzIGVtcHR5LCB3ZSBzdGlsbCBuZWVkIHRvIGNyZWF0ZSBhIENQVVxuICAgICAgICAgIC8vIHRlbnNvciBmb3IgaXQuIFRoZXJlIGlzIG5vIG1hcHBpbmcgR1BVIGJ1ZmZlciBmb3IgYW4gZW1wdHkgdGVuc29yLlxuICAgICAgICAgIGlmIChwcmVmZXJyZWRMb2NhdGlvbiA9PT0gJ2dwdS1idWZmZXInICYmIHNpemUgPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBnZXRCdWZmZXIgPSBCVUlMRF9ERUZTLlVTRV9XRUJHUFVfRVAgPyB3YXNtLndlYmdwdUdldEJ1ZmZlciA6IHdhc20uanNlcEdldEJ1ZmZlcjtcbiAgICAgICAgICAgIGlmICghZ2V0QnVmZmVyKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncHJlZmVycmVkTG9jYXRpb24gXCJncHUtYnVmZmVyXCIgaXMgbm90IHN1cHBvcnRlZCB3aXRob3V0IHVzaW5nIFdlYkdQVS4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGdwdUJ1ZmZlciA9IGdldEJ1ZmZlcihkYXRhT2Zmc2V0KTtcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlclNpemUgPSBjYWxjdWxhdGVUZW5zb3JTaXplSW5CeXRlcyhkYXRhVHlwZSwgc2l6ZSk7XG4gICAgICAgICAgICBpZiAoYnVmZmVyU2l6ZSA9PT0gdW5kZWZpbmVkIHx8ICFpc0dwdUJ1ZmZlclN1cHBvcnRlZFR5cGUodHlwZSkpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7dHlwZX1gKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gZG8gbm90IHJlbGVhc2UgdGhlIHRlbnNvciByaWdodCBub3cuIGl0IHdpbGwgYmUgcmVsZWFzZWQgd2hlbiB1c2VyIGNhbGxzIHRlbnNvci5kaXNwb3NlKCkuXG4gICAgICAgICAgICBrZWVwT3V0cHV0VGVuc29yID0gdHJ1ZTtcblxuICAgICAgICAgICAgaWYgKEJVSUxEX0RFRlMuVVNFX1dFQkdQVV9FUCkge1xuICAgICAgICAgICAgICB3YXNtLndlYmdwdVJlZ2lzdGVyQnVmZmVyIShncHVCdWZmZXIsIHNlc3Npb25JZCwgZGF0YU9mZnNldCk7XG4gICAgICAgICAgICAgIGNvbnN0IGRvd25sb2FkRGF0YUZ1bmN0aW9uID0gd2FzbS53ZWJncHVDcmVhdGVEb3dubG9hZGVyIShncHVCdWZmZXIsIGJ1ZmZlclNpemUsIHNlc3Npb25JZCk7XG4gICAgICAgICAgICAgIG91dHB1dC5wdXNoKFtcbiAgICAgICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgICAgIGRpbXMsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgZ3B1QnVmZmVyLFxuICAgICAgICAgICAgICAgICAgZG93bmxvYWQ6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJyYXlCdWZmZXIgPSBhd2FpdCBkb3dubG9hZERhdGFGdW5jdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gbmV3ICh0ZW5zb3JUeXBlVG9UeXBlZEFycmF5Q29uc3RydWN0b3IodHlwZSEpKShhcnJheUJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkYXRhIGFzIFRlbnNvci5EYXRhVHlwZU1hcFtUZW5zb3IuR3B1QnVmZmVyRGF0YVR5cGVzXTtcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICBkaXNwb3NlOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXNtLl9PcnRSZWxlYXNlVGVuc29yKHRlbnNvcikgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IHJlbGVhc2UgdGVuc29yLlwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICdncHUtYnVmZmVyJyxcbiAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBvdXRwdXQucHVzaChbXG4gICAgICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgICAgICBkaW1zLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGdwdUJ1ZmZlcixcbiAgICAgICAgICAgICAgICAgIGRvd25sb2FkOiB3YXNtLmpzZXBDcmVhdGVEb3dubG9hZGVyIShncHVCdWZmZXIsIGJ1ZmZlclNpemUsIHR5cGUpLFxuICAgICAgICAgICAgICAgICAgZGlzcG9zZTogKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2FzbS5fT3J0UmVsZWFzZVRlbnNvcih0ZW5zb3IpICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCByZWxlYXNlIHRlbnNvci5cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAnZ3B1LWJ1ZmZlcicsXG4gICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAocHJlZmVycmVkTG9jYXRpb24gPT09ICdtbC10ZW5zb3InICYmIHNpemUgPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBlbnN1cmVUZW5zb3IgPSB3YXNtLndlYm5uRW5zdXJlVGVuc29yO1xuICAgICAgICAgICAgY29uc3QgaXNHcmFwaElucHV0T3V0cHV0VHlwZVN1cHBvcnRlZCA9IHdhc20ud2Vibm5Jc0dyYXBoSW5wdXRPdXRwdXRUeXBlU3VwcG9ydGVkO1xuICAgICAgICAgICAgaWYgKCFlbnN1cmVUZW5zb3IgfHwgIWlzR3JhcGhJbnB1dE91dHB1dFR5cGVTdXBwb3J0ZWQpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdwcmVmZXJyZWRMb2NhdGlvbiBcIm1sLXRlbnNvclwiIGlzIG5vdCBzdXBwb3J0ZWQgd2l0aG91dCB1c2luZyBXZWJOTi4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHRlbnNvclNpemUgPSBjYWxjdWxhdGVUZW5zb3JTaXplSW5CeXRlcyhkYXRhVHlwZSwgc2l6ZSk7XG4gICAgICAgICAgICBpZiAodGVuc29yU2l6ZSA9PT0gdW5kZWZpbmVkIHx8ICFpc01MVGVuc29yU3VwcG9ydGVkVHlwZSh0eXBlKSkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGRhdGEgdHlwZTogJHt0eXBlfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc0dyYXBoSW5wdXRPdXRwdXRUeXBlU3VwcG9ydGVkKHNlc3Npb25JZCwgdHlwZSwgZmFsc2UpKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICBgcHJlZmVycmVkTG9jYXRpb24gXCJtbC10ZW5zb3JcIiBmb3IgJHt0eXBlfSBvdXRwdXQgaXMgbm90IHN1cHBvcnRlZCBieSBjdXJyZW50IFdlYk5OIENvbnRleHQuYCxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgdGhlIGdyYXBoIGhhcyBiZWVuIHBhcnRpdGlvbmVkLCB0aGUgb3V0cHV0IHRlbnNvciBtYXkgaGF2ZSBub3QgYmVlbiBjcmVhdGVkLiBGb3IgdGhpcyByZWFzb24sIHdlIHVzZVxuICAgICAgICAgICAgLy8gZW5zdXJlVGVuc29yIHRvIGdldC9jcmVhdGUgdGhlIE1MVGVuc29yLiBJbiB3aGljaCBjYXNlLCB3ZSBkb24ndCBuZWVkIHRvIGNvcHkgdGhlIGRhdGEgaWYgYSBuZXcgdGVuc29yXG4gICAgICAgICAgICAvLyBoYXMgYmVlbiBjcmVhdGVkLlxuICAgICAgICAgICAgY29uc3QgbWxUZW5zb3IgPSBhd2FpdCBlbnN1cmVUZW5zb3Ioc2Vzc2lvbklkLCBkYXRhT2Zmc2V0LCBkYXRhVHlwZSwgZGltcywgZmFsc2UpO1xuXG4gICAgICAgICAgICAvLyBkbyBub3QgcmVsZWFzZSB0aGUgdGVuc29yIHJpZ2h0IG5vdy4gaXQgd2lsbCBiZSByZWxlYXNlZCB3aGVuIHVzZXIgY2FsbHMgdGVuc29yLmRpc3Bvc2UoKS5cbiAgICAgICAgICAgIGtlZXBPdXRwdXRUZW5zb3IgPSB0cnVlO1xuXG4gICAgICAgICAgICBvdXRwdXQucHVzaChbXG4gICAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICAgIGRpbXMsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBtbFRlbnNvcixcbiAgICAgICAgICAgICAgICBkb3dubG9hZDogd2FzbS53ZWJubkNyZWF0ZU1MVGVuc29yRG93bmxvYWRlciEoZGF0YU9mZnNldCwgdHlwZSksXG4gICAgICAgICAgICAgICAgZGlzcG9zZTogKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgd2FzbS53ZWJublJlbGVhc2VUZW5zb3JJZCEoZGF0YU9mZnNldCk7XG4gICAgICAgICAgICAgICAgICB3YXNtLl9PcnRSZWxlYXNlVGVuc29yKHRlbnNvcik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgJ21sLXRlbnNvcicsXG4gICAgICAgICAgICBdKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHByZWZlcnJlZExvY2F0aW9uID09PSAnbWwtdGVuc29yLWNwdS1vdXRwdXQnICYmIHNpemUgPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBkYXRhID0gd2FzbS53ZWJubkNyZWF0ZU1MVGVuc29yRG93bmxvYWRlciEoZGF0YU9mZnNldCwgdHlwZSBhcyBUZW5zb3IuTUxUZW5zb3JEYXRhVHlwZXMpKCk7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IG91dHB1dC5sZW5ndGg7XG4gICAgICAgICAgICAvLyBEZWxheSB0aGUgZGF0YSBkb3dubG9hZCBhbmQgcmVsZWFzaW5nIHRoZSB0ZW5zb3IgdW50aWwgd2UgY2FuIHdhaXQgZm9yIGFsbCBvdXRwdXQgdGVuc29ycyB0byBiZSBkb3dubG9hZGVkLlxuICAgICAgICAgICAga2VlcE91dHB1dFRlbnNvciA9IHRydWU7XG4gICAgICAgICAgICBvdXRwdXRQcm9taXNlcy5wdXNoKFxuICAgICAgICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdDogW251bWJlciwgVGVuc29yLkRhdGFUeXBlXSA9IFtpbmRleCwgYXdhaXQgZGF0YV07XG4gICAgICAgICAgICAgICAgd2FzbS53ZWJublJlbGVhc2VUZW5zb3JJZCEoZGF0YU9mZnNldCk7XG4gICAgICAgICAgICAgICAgd2FzbS5fT3J0UmVsZWFzZVRlbnNvcih0ZW5zb3IpO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgIH0pKCksXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgb3V0cHV0LnB1c2goW3R5cGUsIGRpbXMsIFtdLCAnY3B1J10pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCB0eXBlZEFycmF5Q29uc3RydWN0b3IgPSB0ZW5zb3JUeXBlVG9UeXBlZEFycmF5Q29uc3RydWN0b3IodHlwZSk7XG4gICAgICAgICAgICBjb25zdCBkYXRhID0gbmV3IHR5cGVkQXJyYXlDb25zdHJ1Y3RvcihzaXplKTtcbiAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KGRhdGEuYnVmZmVyLCBkYXRhLmJ5dGVPZmZzZXQsIGRhdGEuYnl0ZUxlbmd0aCkuc2V0KFxuICAgICAgICAgICAgICB3YXNtLkhFQVBVOC5zdWJhcnJheShkYXRhT2Zmc2V0LCBkYXRhT2Zmc2V0ICsgZGF0YS5ieXRlTGVuZ3RoKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBvdXRwdXQucHVzaChbdHlwZSwgZGltcywgZGF0YSwgJ2NwdSddKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHdhc20uc3RhY2tSZXN0b3JlKGJlZm9yZUdldFRlbnNvckRhdGFTdGFjayk7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJyAmJiBkYXRhT2Zmc2V0KSB7XG4gICAgICAgICAgd2FzbS5fZnJlZShkYXRhT2Zmc2V0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWtlZXBPdXRwdXRUZW5zb3IpIHtcbiAgICAgICAgICB3YXNtLl9PcnRSZWxlYXNlVGVuc29yKHRlbnNvcik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaW9CaW5kaW5nU3RhdGUgJiYgIWVuYWJsZUdyYXBoQ2FwdHVyZSkge1xuICAgICAgaWYgKHdhc20uX09ydENsZWFyQm91bmRPdXRwdXRzKGlvQmluZGluZ1N0YXRlLmhhbmRsZSkgIT09IDApIHtcbiAgICAgICAgY2hlY2tMYXN0RXJyb3IoXCJDYW4ndCBjbGVhciBib3VuZCBvdXRwdXRzLlwiKTtcbiAgICAgIH1cbiAgICAgIGFjdGl2ZVNlc3Npb25zLnNldChzZXNzaW9uSWQsIFtcbiAgICAgICAgc2Vzc2lvbkhhbmRsZSxcbiAgICAgICAgaW5wdXROYW1lc1VURjhFbmNvZGVkLFxuICAgICAgICBvdXRwdXROYW1lc1VURjhFbmNvZGVkLFxuICAgICAgICBpb0JpbmRpbmdTdGF0ZSxcbiAgICAgICAgZW5hYmxlR3JhcGhDYXB0dXJlLFxuICAgICAgICBmYWxzZSxcbiAgICAgIF0pO1xuICAgIH1cbiAgICAvLyBXYWl0IGZvciBhbGwgb3V0cHV0IHRlbnNvciBkYXRhIHRvIGJlIGRvd25sb2FkZWQuXG4gICAgZm9yIChjb25zdCBbaW5kZXgsIGRhdGFdIG9mIGF3YWl0IFByb21pc2UuYWxsKG91dHB1dFByb21pc2VzKSkge1xuICAgICAgb3V0cHV0W2luZGV4XVsyXSA9IGRhdGE7XG4gICAgfVxuICAgIHJldHVybiBvdXRwdXQ7XG4gIH0gZmluYWxseSB7XG4gICAgd2FzbS53ZWJubk9uUnVuRW5kPy4oc2Vzc2lvbkhhbmRsZSk7XG5cbiAgICB3YXNtLnN0YWNrUmVzdG9yZShiZWZvcmVSdW5TdGFjayk7XG5cbiAgICBpZiAoQlVJTERfREVGUy5VU0VfV0VCR1BVX0VQKSB7XG4gICAgICBpbnB1dFRlbnNvcnMuZm9yRWFjaCgodCkgPT4ge1xuICAgICAgICBpZiAodCAmJiB0WzNdID09PSAnZ3B1LWJ1ZmZlcicpIHtcbiAgICAgICAgICB3YXNtLndlYmdwdVVucmVnaXN0ZXJCdWZmZXIhKHRbMl0uZ3B1QnVmZmVyKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBvdXRwdXRUZW5zb3JzLmZvckVhY2goKHQpID0+IHtcbiAgICAgICAgaWYgKHQgJiYgdFszXSA9PT0gJ2dwdS1idWZmZXInKSB7XG4gICAgICAgICAgd2FzbS53ZWJncHVVbnJlZ2lzdGVyQnVmZmVyISh0WzJdLmdwdUJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICBpbnB1dFRlbnNvckhhbmRsZXMuZm9yRWFjaCgodikgPT4gd2FzbS5fT3J0UmVsZWFzZVRlbnNvcih2KSk7XG4gICAgb3V0cHV0VGVuc29ySGFuZGxlcy5mb3JFYWNoKCh2KSA9PiB3YXNtLl9PcnRSZWxlYXNlVGVuc29yKHYpKTtcbiAgICBpbnB1dE91dHB1dEFsbG9jcy5mb3JFYWNoKChwKSA9PiB3YXNtLl9mcmVlKHApKTtcblxuICAgIGlmIChydW5PcHRpb25zSGFuZGxlICE9PSAwKSB7XG4gICAgICB3YXNtLl9PcnRSZWxlYXNlUnVuT3B0aW9ucyhydW5PcHRpb25zSGFuZGxlKTtcbiAgICB9XG4gICAgcnVuT3B0aW9uc0FsbG9jcy5mb3JFYWNoKChwKSA9PiB3YXNtLl9mcmVlKHApKTtcbiAgfVxufTtcblxuLyoqXG4gKiBlbmQgcHJvZmlsaW5nXG4gKi9cbmV4cG9ydCBjb25zdCBlbmRQcm9maWxpbmcgPSAoc2Vzc2lvbklkOiBudW1iZXIpOiB2b2lkID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gIGNvbnN0IHNlc3Npb24gPSBhY3RpdmVTZXNzaW9ucy5nZXQoc2Vzc2lvbklkKTtcbiAgaWYgKCFzZXNzaW9uKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHNlc3Npb24gaWQnKTtcbiAgfVxuICBjb25zdCBzZXNzaW9uSGFuZGxlID0gc2Vzc2lvblswXTtcblxuICAvLyBwcm9maWxlIGZpbGUgbmFtZSBpcyBub3QgdXNlZCB5ZXQsIGJ1dCBpdCBtdXN0IGJlIGZyZWVkLlxuICBjb25zdCBwcm9maWxlRmlsZU5hbWUgPSB3YXNtLl9PcnRFbmRQcm9maWxpbmcoc2Vzc2lvbkhhbmRsZSk7XG4gIGlmIChwcm9maWxlRmlsZU5hbWUgPT09IDApIHtcbiAgICBjaGVja0xhc3RFcnJvcihcIkNhbid0IGdldCBhbiBwcm9maWxlIGZpbGUgbmFtZS5cIik7XG4gIH1cbiAgd2FzbS5fT3J0RnJlZShwcm9maWxlRmlsZU5hbWUpO1xufTtcblxuZXhwb3J0IGNvbnN0IGV4dHJhY3RUcmFuc2ZlcmFibGVCdWZmZXJzID0gKHRlbnNvcnM6IHJlYWRvbmx5IFNlcmlhbGl6YWJsZVRlbnNvck1ldGFkYXRhW10pOiBBcnJheUJ1ZmZlckxpa2VbXSA9PiB7XG4gIGNvbnN0IGJ1ZmZlcnM6IEFycmF5QnVmZmVyTGlrZVtdID0gW107XG4gIGZvciAoY29uc3QgdGVuc29yIG9mIHRlbnNvcnMpIHtcbiAgICBjb25zdCBkYXRhID0gdGVuc29yWzJdO1xuICAgIGlmICghQXJyYXkuaXNBcnJheShkYXRhKSAmJiAnYnVmZmVyJyBpbiBkYXRhKSB7XG4gICAgICBidWZmZXJzLnB1c2goZGF0YS5idWZmZXIpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gYnVmZmVycztcbn07XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7IGVudiwgSW5mZXJlbmNlU2Vzc2lvbiB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7XG4gIE9ydFdhc21NZXNzYWdlLFxuICBTZXJpYWxpemFibGVJbnRlcm5hbEJ1ZmZlcixcbiAgU2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhLFxuICBTZXJpYWxpemFibGVUZW5zb3JNZXRhZGF0YSxcbiAgVGVuc29yTWV0YWRhdGEsXG59IGZyb20gJy4vcHJveHktbWVzc2FnZXMnO1xuaW1wb3J0ICogYXMgY29yZSBmcm9tICcuL3dhc20tY29yZS1pbXBsJztcbmltcG9ydCB7IGluaXRpYWxpemVXZWJBc3NlbWJseSB9IGZyb20gJy4vd2FzbS1mYWN0b3J5JztcbmltcG9ydCB7XG4gIGltcG9ydFByb3h5V29ya2VyLFxuICBpbmZlcldhc21QYXRoUHJlZml4RnJvbVNjcmlwdFNyYyxcbiAgaXNFc21JbXBvcnRNZXRhVXJsSGFyZGNvZGVkQXNGaWxlVXJpLFxufSBmcm9tICcuL3dhc20tdXRpbHMtaW1wb3J0JztcblxuY29uc3QgaXNQcm94eSA9ICgpOiBib29sZWFuID0+ICEhZW52Lndhc20ucHJveHkgJiYgdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJztcbmxldCBwcm94eVdvcmtlcjogV29ya2VyIHwgdW5kZWZpbmVkO1xubGV0IGluaXRpYWxpemluZyA9IGZhbHNlO1xubGV0IGluaXRpYWxpemVkID0gZmFsc2U7XG5sZXQgYWJvcnRlZCA9IGZhbHNlO1xubGV0IHRlbXBvcmFyeU9iamVjdFVybDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG50eXBlIFByb21pc2VDYWxsYmFja3M8VCA9IHZvaWQ+ID0gW3Jlc29sdmU6IChyZXN1bHQ6IFQpID0+IHZvaWQsIHJlamVjdDogKHJlYXNvbjogdW5rbm93bikgPT4gdm9pZF07XG5sZXQgaW5pdFdhc21DYWxsYmFja3M6IFByb21pc2VDYWxsYmFja3M7XG5jb25zdCBxdWV1ZWRDYWxsYmFja3M6IE1hcDxPcnRXYXNtTWVzc2FnZVsndHlwZSddLCBBcnJheTxQcm9taXNlQ2FsbGJhY2tzPHVua25vd24+Pj4gPSBuZXcgTWFwKCk7XG5cbmNvbnN0IGVucXVldWVDYWxsYmFja3MgPSAodHlwZTogT3J0V2FzbU1lc3NhZ2VbJ3R5cGUnXSwgY2FsbGJhY2tzOiBQcm9taXNlQ2FsbGJhY2tzPHVua25vd24+KTogdm9pZCA9PiB7XG4gIGNvbnN0IHF1ZXVlID0gcXVldWVkQ2FsbGJhY2tzLmdldCh0eXBlKTtcbiAgaWYgKHF1ZXVlKSB7XG4gICAgcXVldWUucHVzaChjYWxsYmFja3MpO1xuICB9IGVsc2Uge1xuICAgIHF1ZXVlZENhbGxiYWNrcy5zZXQodHlwZSwgW2NhbGxiYWNrc10pO1xuICB9XG59O1xuXG5jb25zdCBlbnN1cmVXb3JrZXIgPSAoKTogdm9pZCA9PiB7XG4gIGlmIChpbml0aWFsaXppbmcgfHwgIWluaXRpYWxpemVkIHx8IGFib3J0ZWQgfHwgIXByb3h5V29ya2VyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd3b3JrZXIgbm90IHJlYWR5Jyk7XG4gIH1cbn07XG5cbmNvbnN0IG9uUHJveHlXb3JrZXJNZXNzYWdlID0gKGV2OiBNZXNzYWdlRXZlbnQ8T3J0V2FzbU1lc3NhZ2U+KTogdm9pZCA9PiB7XG4gIHN3aXRjaCAoZXYuZGF0YS50eXBlKSB7XG4gICAgY2FzZSAnaW5pdC13YXNtJzpcbiAgICAgIGluaXRpYWxpemluZyA9IGZhbHNlO1xuICAgICAgaWYgKGV2LmRhdGEuZXJyKSB7XG4gICAgICAgIGFib3J0ZWQgPSB0cnVlO1xuICAgICAgICBpbml0V2FzbUNhbGxiYWNrc1sxXShldi5kYXRhLmVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbml0aWFsaXplZCA9IHRydWU7XG4gICAgICAgIGluaXRXYXNtQ2FsbGJhY2tzWzBdKCk7XG4gICAgICB9XG4gICAgICBpZiAodGVtcG9yYXJ5T2JqZWN0VXJsKSB7XG4gICAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwodGVtcG9yYXJ5T2JqZWN0VXJsKTtcbiAgICAgICAgdGVtcG9yYXJ5T2JqZWN0VXJsID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaW5pdC1lcCc6XG4gICAgY2FzZSAnY29weS1mcm9tJzpcbiAgICBjYXNlICdjcmVhdGUnOlxuICAgIGNhc2UgJ3JlbGVhc2UnOlxuICAgIGNhc2UgJ3J1bic6XG4gICAgY2FzZSAnZW5kLXByb2ZpbGluZyc6IHtcbiAgICAgIGNvbnN0IGNhbGxiYWNrcyA9IHF1ZXVlZENhbGxiYWNrcy5nZXQoZXYuZGF0YS50eXBlKSE7XG4gICAgICBpZiAoZXYuZGF0YS5lcnIpIHtcbiAgICAgICAgY2FsbGJhY2tzLnNoaWZ0KCkhWzFdKGV2LmRhdGEuZXJyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNhbGxiYWNrcy5zaGlmdCgpIVswXShldi5kYXRhLm91dCEpO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGRlZmF1bHQ6XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBpbml0aWFsaXplV2ViQXNzZW1ibHlBbmRPcnRSdW50aW1lID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZiAoaW5pdGlhbGl6ZWQpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGluaXRpYWxpemluZykge1xuICAgIHRocm93IG5ldyBFcnJvcihcIm11bHRpcGxlIGNhbGxzIHRvICdpbml0V2FzbSgpJyBkZXRlY3RlZC5cIik7XG4gIH1cbiAgaWYgKGFib3J0ZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJwcmV2aW91cyBjYWxsIHRvICdpbml0V2FzbSgpJyBmYWlsZWQuXCIpO1xuICB9XG5cbiAgaW5pdGlhbGl6aW5nID0gdHJ1ZTtcblxuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBwcm94eVdvcmtlcj8udGVybWluYXRlKCk7XG5cbiAgICAgIHZvaWQgaW1wb3J0UHJveHlXb3JrZXIoKS50aGVuKChbb2JqZWN0VXJsLCB3b3JrZXJdKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcHJveHlXb3JrZXIgPSB3b3JrZXI7XG4gICAgICAgICAgcHJveHlXb3JrZXIub25lcnJvciA9IChldjogRXJyb3JFdmVudCkgPT4gcmVqZWN0KGV2KTtcbiAgICAgICAgICBwcm94eVdvcmtlci5vbm1lc3NhZ2UgPSBvblByb3h5V29ya2VyTWVzc2FnZTtcbiAgICAgICAgICBpbml0V2FzbUNhbGxiYWNrcyA9IFtyZXNvbHZlLCByZWplY3RdO1xuICAgICAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0geyB0eXBlOiAnaW5pdC13YXNtJywgaW46IGVudiB9O1xuXG4gICAgICAgICAgLy8gaWYgdGhlIHByb3h5IHdvcmtlciBpcyBsb2FkZWQgZnJvbSBhIGJsb2IgVVJMLCB3ZSBuZWVkIHRvIG1ha2Ugc3VyZSB0aGUgcGF0aCBpbmZvcm1hdGlvbiBpcyBub3QgbG9zdC5cbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vIHdoZW4gYGVudi53YXNtLndhc21QYXRoc2AgaXMgbm90IHNldCwgd2UgbmVlZCB0byBwYXNzIHRoZSBwYXRoIGluZm9ybWF0aW9uIHRvIHRoZSB3b3JrZXIuXG4gICAgICAgICAgLy9cbiAgICAgICAgICBpZiAoIUJVSUxEX0RFRlMuRU5BQkxFX0JVTkRMRV9XQVNNX0pTICYmICFtZXNzYWdlLmluIS53YXNtLndhc21QYXRocyAmJiBvYmplY3RVcmwpIHtcbiAgICAgICAgICAgIC8vIGZvciBhIGJ1aWxkIG5vdCBidW5kbGVkIHRoZSB3YXNtIEpTLCB3ZSBuZWVkIHRvIHBhc3MgdGhlIHBhdGggcHJlZml4IHRvIHRoZSB3b3JrZXIuXG4gICAgICAgICAgICAvLyB0aGUgcGF0aCBwcmVmaXggd2lsbCBiZSB1c2VkIHRvIHJlc29sdmUgdGhlIHBhdGggdG8gYm90aCB0aGUgd2FzbSBKUyBhbmQgdGhlIHdhc20gZmlsZS5cbiAgICAgICAgICAgIGNvbnN0IGluZmVycmVkV2FzbVBhdGhQcmVmaXggPSBpbmZlcldhc21QYXRoUHJlZml4RnJvbVNjcmlwdFNyYygpO1xuICAgICAgICAgICAgaWYgKGluZmVycmVkV2FzbVBhdGhQcmVmaXgpIHtcbiAgICAgICAgICAgICAgbWVzc2FnZS5pbiEud2FzbS53YXNtUGF0aHMgPSBpbmZlcnJlZFdhc21QYXRoUHJlZml4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIEJVSUxEX0RFRlMuSVNfRVNNICYmXG4gICAgICAgICAgICBCVUlMRF9ERUZTLkVOQUJMRV9CVU5ETEVfV0FTTV9KUyAmJlxuICAgICAgICAgICAgIW1lc3NhZ2UuaW4hLndhc20ud2FzbVBhdGhzICYmXG4gICAgICAgICAgICAob2JqZWN0VXJsIHx8IGlzRXNtSW1wb3J0TWV0YVVybEhhcmRjb2RlZEFzRmlsZVVyaSlcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIC8vIGZvciBhIGJ1aWxkIGJ1bmRsZWQgdGhlIHdhc20gSlMsIGlmIGVpdGhlciBvZiB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgaXMgbWV0OlxuICAgICAgICAgICAgLy8gLSB0aGUgcHJveHkgd29ya2VyIGlzIGxvYWRlZCBmcm9tIGEgYmxvYiBVUkxcbiAgICAgICAgICAgIC8vIC0gYGltcG9ydC5tZXRhLnVybGAgaXMgYSBmaWxlIFVSTCwgaXQgbWVhbnMgaXQgaXMgb3ZlcndyaXRlbiBieSB0aGUgYnVuZGxlci5cbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBpbiBlaXRoZXIgY2FzZSwgdGhlIHBhdGggaW5mb3JtYXRpb24gaXMgbG9zdCwgd2UgbmVlZCB0byBwYXNzIHRoZSBwYXRoIG9mIHRoZSAud2FzbSBmaWxlIHRvIHRoZSB3b3JrZXIuXG4gICAgICAgICAgICAvLyB3ZSBuZWVkIHRvIHVzZSB0aGUgYnVuZGxlciBwcmVmZXJyZWQgVVJMIGZvcm1hdDpcbiAgICAgICAgICAgIC8vIG5ldyBVUkwoJ2ZpbGVuYW1lJywgaW1wb3J0Lm1ldGEudXJsKVxuICAgICAgICAgICAgLy8gc28gdGhhdCB0aGUgYnVuZGxlciBjYW4gaGFuZGxlIHRoZSBmaWxlIHVzaW5nIGNvcnJlc3BvbmRpbmcgbG9hZGVycy5cbiAgICAgICAgICAgIG1lc3NhZ2UuaW4hLndhc20ud2FzbVBhdGhzID0ge1xuICAgICAgICAgICAgICB3YXNtOiAhQlVJTERfREVGUy5ESVNBQkxFX0pTRVBcbiAgICAgICAgICAgICAgICA/IG5ldyBVUkwoJ29ydC13YXNtLXNpbWQtdGhyZWFkZWQuanNlcC53YXNtJywgQlVJTERfREVGUy5FU01fSU1QT1JUX01FVEFfVVJMKS5ocmVmXG4gICAgICAgICAgICAgICAgOiBuZXcgVVJMKCdvcnQtd2FzbS1zaW1kLXRocmVhZGVkLndhc20nLCBCVUlMRF9ERUZTLkVTTV9JTVBPUlRfTUVUQV9VUkwpLmhyZWYsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgICBwcm94eVdvcmtlci5wb3N0TWVzc2FnZShtZXNzYWdlKTtcbiAgICAgICAgICB0ZW1wb3JhcnlPYmplY3RVcmwgPSBvYmplY3RVcmw7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgIH0sIHJlamVjdCk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGluaXRpYWxpemVXZWJBc3NlbWJseShlbnYud2FzbSk7XG4gICAgICBhd2FpdCBjb3JlLmluaXRSdW50aW1lKGVudik7XG4gICAgICBpbml0aWFsaXplZCA9IHRydWU7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgYWJvcnRlZCA9IHRydWU7XG4gICAgICB0aHJvdyBlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcbiAgICB9XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBpbml0aWFsaXplT3J0RXAgPSBhc3luYyAoZXBOYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICBlbnN1cmVXb3JrZXIoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgZW5xdWV1ZUNhbGxiYWNrcygnaW5pdC1lcCcsIFtyZXNvbHZlLCByZWplY3RdKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0geyB0eXBlOiAnaW5pdC1lcCcsIGluOiB7IGVwTmFtZSwgZW52IH0gfTtcbiAgICAgIHByb3h5V29ya2VyIS5wb3N0TWVzc2FnZShtZXNzYWdlKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBhd2FpdCBjb3JlLmluaXRFcChlbnYsIGVwTmFtZSk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBjb3B5RnJvbUV4dGVybmFsQnVmZmVyID0gYXN5bmMgKGJ1ZmZlcjogVWludDhBcnJheSk6IFByb21pc2U8U2VyaWFsaXphYmxlSW50ZXJuYWxCdWZmZXI+ID0+IHtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICBlbnN1cmVXb3JrZXIoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8U2VyaWFsaXphYmxlSW50ZXJuYWxCdWZmZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGVucXVldWVDYWxsYmFja3MoJ2NvcHktZnJvbScsIFtyZXNvbHZlLCByZWplY3RdKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0geyB0eXBlOiAnY29weS1mcm9tJywgaW46IHsgYnVmZmVyIH0gfTtcbiAgICAgIHByb3h5V29ya2VyIS5wb3N0TWVzc2FnZShtZXNzYWdlLCBbYnVmZmVyLmJ1ZmZlcl0pO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBjb3JlLmNvcHlGcm9tRXh0ZXJuYWxCdWZmZXIoYnVmZmVyKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVNlc3Npb24gPSBhc3luYyAoXG4gIG1vZGVsOiBTZXJpYWxpemFibGVJbnRlcm5hbEJ1ZmZlciB8IFVpbnQ4QXJyYXksXG4gIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zLFxuKTogUHJvbWlzZTxTZXJpYWxpemFibGVTZXNzaW9uTWV0YWRhdGE+ID0+IHtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICAvLyBjaGVjayB1bnN1cHBvcnRlZCBvcHRpb25zXG4gICAgaWYgKG9wdGlvbnM/LnByZWZlcnJlZE91dHB1dExvY2F0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Nlc3Npb24gb3B0aW9uIFwicHJlZmVycmVkT3V0cHV0TG9jYXRpb25cIiBpcyBub3Qgc3VwcG9ydGVkIGZvciBwcm94eS4nKTtcbiAgICB9XG4gICAgZW5zdXJlV29ya2VyKCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPFNlcmlhbGl6YWJsZVNlc3Npb25NZXRhZGF0YT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgZW5xdWV1ZUNhbGxiYWNrcygnY3JlYXRlJywgW3Jlc29sdmUsIHJlamVjdF0pO1xuICAgICAgY29uc3QgbWVzc2FnZTogT3J0V2FzbU1lc3NhZ2UgPSB7IHR5cGU6ICdjcmVhdGUnLCBpbjogeyBtb2RlbCwgb3B0aW9uczogeyAuLi5vcHRpb25zIH0gfSB9O1xuICAgICAgY29uc3QgdHJhbnNmZXJhYmxlOiBUcmFuc2ZlcmFibGVbXSA9IFtdO1xuICAgICAgaWYgKG1vZGVsIGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuICAgICAgICB0cmFuc2ZlcmFibGUucHVzaChtb2RlbC5idWZmZXIpO1xuICAgICAgfVxuICAgICAgcHJveHlXb3JrZXIhLnBvc3RNZXNzYWdlKG1lc3NhZ2UsIHRyYW5zZmVyYWJsZSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGNvcmUuY3JlYXRlU2Vzc2lvbihtb2RlbCwgb3B0aW9ucyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCByZWxlYXNlU2Vzc2lvbiA9IGFzeW5jIChzZXNzaW9uSWQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIGVuc3VyZVdvcmtlcigpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBlbnF1ZXVlQ2FsbGJhY2tzKCdyZWxlYXNlJywgW3Jlc29sdmUsIHJlamVjdF0pO1xuICAgICAgY29uc3QgbWVzc2FnZTogT3J0V2FzbU1lc3NhZ2UgPSB7IHR5cGU6ICdyZWxlYXNlJywgaW46IHNlc3Npb25JZCB9O1xuICAgICAgcHJveHlXb3JrZXIhLnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGNvcmUucmVsZWFzZVNlc3Npb24oc2Vzc2lvbklkKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHJ1biA9IGFzeW5jIChcbiAgc2Vzc2lvbklkOiBudW1iZXIsXG4gIGlucHV0SW5kaWNlczogbnVtYmVyW10sXG4gIGlucHV0czogVGVuc29yTWV0YWRhdGFbXSxcbiAgb3V0cHV0SW5kaWNlczogbnVtYmVyW10sXG4gIG91dHB1dHM6IEFycmF5PFRlbnNvck1ldGFkYXRhIHwgbnVsbD4sXG4gIG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uUnVuT3B0aW9ucyxcbik6IFByb21pc2U8VGVuc29yTWV0YWRhdGFbXT4gPT4ge1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIC8vIGNoZWNrIGlucHV0cyBsb2NhdGlvblxuICAgIGlmIChpbnB1dHMuc29tZSgodCkgPT4gdFszXSAhPT0gJ2NwdScpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0IHRlbnNvciBvbiBHUFUgaXMgbm90IHN1cHBvcnRlZCBmb3IgcHJveHkuJyk7XG4gICAgfVxuICAgIC8vIGNoZWNrIG91dHB1dHMgbG9jYXRpb25cbiAgICBpZiAob3V0cHV0cy5zb21lKCh0KSA9PiB0KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdwcmUtYWxsb2NhdGVkIG91dHB1dCB0ZW5zb3IgaXMgbm90IHN1cHBvcnRlZCBmb3IgcHJveHkuJyk7XG4gICAgfVxuICAgIGVuc3VyZVdvcmtlcigpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxTZXJpYWxpemFibGVUZW5zb3JNZXRhZGF0YVtdPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBlbnF1ZXVlQ2FsbGJhY2tzKCdydW4nLCBbcmVzb2x2ZSwgcmVqZWN0XSk7XG4gICAgICBjb25zdCBzZXJpYWxpemFibGVJbnB1dHMgPSBpbnB1dHMgYXMgU2VyaWFsaXphYmxlVGVuc29yTWV0YWRhdGFbXTsgLy8gZXZlcnkgaW5wdXQgaXMgb24gQ1BVLlxuICAgICAgY29uc3QgbWVzc2FnZTogT3J0V2FzbU1lc3NhZ2UgPSB7XG4gICAgICAgIHR5cGU6ICdydW4nLFxuICAgICAgICBpbjogeyBzZXNzaW9uSWQsIGlucHV0SW5kaWNlcywgaW5wdXRzOiBzZXJpYWxpemFibGVJbnB1dHMsIG91dHB1dEluZGljZXMsIG9wdGlvbnMgfSxcbiAgICAgIH07XG4gICAgICBwcm94eVdvcmtlciEucG9zdE1lc3NhZ2UobWVzc2FnZSwgY29yZS5leHRyYWN0VHJhbnNmZXJhYmxlQnVmZmVycyhzZXJpYWxpemFibGVJbnB1dHMpKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gY29yZS5ydW4oc2Vzc2lvbklkLCBpbnB1dEluZGljZXMsIGlucHV0cywgb3V0cHV0SW5kaWNlcywgb3V0cHV0cywgb3B0aW9ucyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBlbmRQcm9maWxpbmcgPSBhc3luYyAoc2Vzc2lvbklkOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICBlbnN1cmVXb3JrZXIoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgZW5xdWV1ZUNhbGxiYWNrcygnZW5kLXByb2ZpbGluZycsIFtyZXNvbHZlLCByZWplY3RdKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0geyB0eXBlOiAnZW5kLXByb2ZpbGluZycsIGluOiBzZXNzaW9uSWQgfTtcbiAgICAgIHByb3h5V29ya2VyIS5wb3N0TWVzc2FnZShtZXNzYWdlKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBjb3JlLmVuZFByb2ZpbGluZyhzZXNzaW9uSWQpO1xuICB9XG59O1xuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1xuICBJbmZlcmVuY2VTZXNzaW9uLFxuICBJbmZlcmVuY2VTZXNzaW9uSGFuZGxlcixcbiAgU2Vzc2lvbkhhbmRsZXIsXG4gIFRlbnNvcixcbiAgVFJBQ0VfRlVOQ19CRUdJTixcbiAgVFJBQ0VfRlVOQ19FTkQsXG59IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7IFNlcmlhbGl6YWJsZUludGVybmFsQnVmZmVyLCBUZW5zb3JNZXRhZGF0YSB9IGZyb20gJy4vcHJveHktbWVzc2FnZXMnO1xuaW1wb3J0IHsgY29weUZyb21FeHRlcm5hbEJ1ZmZlciwgY3JlYXRlU2Vzc2lvbiwgZW5kUHJvZmlsaW5nLCByZWxlYXNlU2Vzc2lvbiwgcnVuIH0gZnJvbSAnLi9wcm94eS13cmFwcGVyJztcbmltcG9ydCB7IGlzR3B1QnVmZmVyU3VwcG9ydGVkVHlwZSwgaXNNTFRlbnNvclN1cHBvcnRlZFR5cGUgfSBmcm9tICcuL3dhc20tY29tbW9uJztcbmltcG9ydCB7IGlzTm9kZSB9IGZyb20gJy4vd2FzbS11dGlscy1lbnYnO1xuaW1wb3J0IHsgbG9hZEZpbGUgfSBmcm9tICcuL3dhc20tdXRpbHMtbG9hZC1maWxlJztcblxuZXhwb3J0IGNvbnN0IGVuY29kZVRlbnNvck1ldGFkYXRhID0gKHRlbnNvcjogVGVuc29yLCBnZXROYW1lOiAoKSA9PiBzdHJpbmcpOiBUZW5zb3JNZXRhZGF0YSA9PiB7XG4gIHN3aXRjaCAodGVuc29yLmxvY2F0aW9uKSB7XG4gICAgY2FzZSAnY3B1JzpcbiAgICAgIHJldHVybiBbdGVuc29yLnR5cGUsIHRlbnNvci5kaW1zLCB0ZW5zb3IuZGF0YSwgJ2NwdSddO1xuICAgIGNhc2UgJ2dwdS1idWZmZXInOlxuICAgICAgcmV0dXJuIFt0ZW5zb3IudHlwZSwgdGVuc29yLmRpbXMsIHsgZ3B1QnVmZmVyOiB0ZW5zb3IuZ3B1QnVmZmVyIH0sICdncHUtYnVmZmVyJ107XG4gICAgY2FzZSAnbWwtdGVuc29yJzpcbiAgICAgIHJldHVybiBbdGVuc29yLnR5cGUsIHRlbnNvci5kaW1zLCB7IG1sVGVuc29yOiB0ZW5zb3IubWxUZW5zb3IgfSwgJ21sLXRlbnNvciddO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgZGF0YSBsb2NhdGlvbjogJHt0ZW5zb3IubG9jYXRpb259IGZvciAke2dldE5hbWUoKX1gKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGRlY29kZVRlbnNvck1ldGFkYXRhID0gKHRlbnNvcjogVGVuc29yTWV0YWRhdGEpOiBUZW5zb3IgPT4ge1xuICBzd2l0Y2ggKHRlbnNvclszXSkge1xuICAgIGNhc2UgJ2NwdSc6XG4gICAgICByZXR1cm4gbmV3IFRlbnNvcih0ZW5zb3JbMF0sIHRlbnNvclsyXSwgdGVuc29yWzFdKTtcbiAgICBjYXNlICdncHUtYnVmZmVyJzoge1xuICAgICAgY29uc3QgZGF0YVR5cGUgPSB0ZW5zb3JbMF07XG4gICAgICBpZiAoIWlzR3B1QnVmZmVyU3VwcG9ydGVkVHlwZShkYXRhVHlwZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIGRhdGEgdHlwZTogJHtkYXRhVHlwZX0gZm9yIGRlc2VyaWFsaXppbmcgR1BVIHRlbnNvcmApO1xuICAgICAgfVxuICAgICAgY29uc3QgeyBncHVCdWZmZXIsIGRvd25sb2FkLCBkaXNwb3NlIH0gPSB0ZW5zb3JbMl07XG4gICAgICByZXR1cm4gVGVuc29yLmZyb21HcHVCdWZmZXIoZ3B1QnVmZmVyLCB7IGRhdGFUeXBlLCBkaW1zOiB0ZW5zb3JbMV0sIGRvd25sb2FkLCBkaXNwb3NlIH0pO1xuICAgIH1cbiAgICBjYXNlICdtbC10ZW5zb3InOiB7XG4gICAgICBjb25zdCBkYXRhVHlwZSA9IHRlbnNvclswXTtcbiAgICAgIGlmICghaXNNTFRlbnNvclN1cHBvcnRlZFR5cGUoZGF0YVR5cGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbm90IHN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZGF0YVR5cGV9IGZvciBkZXNlcmlhbGl6aW5nIE1MVGVuc29yIHRlbnNvcmApO1xuICAgICAgfVxuICAgICAgY29uc3QgeyBtbFRlbnNvciwgZG93bmxvYWQsIGRpc3Bvc2UgfSA9IHRlbnNvclsyXTtcbiAgICAgIHJldHVybiBUZW5zb3IuZnJvbU1MVGVuc29yKG1sVGVuc29yLCB7IGRhdGFUeXBlLCBkaW1zOiB0ZW5zb3JbMV0sIGRvd25sb2FkLCBkaXNwb3NlIH0pO1xuICAgIH1cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGRhdGEgbG9jYXRpb246ICR7dGVuc29yWzNdfWApO1xuICB9XG59O1xuXG5leHBvcnQgY2xhc3MgT25ueHJ1bnRpbWVXZWJBc3NlbWJseVNlc3Npb25IYW5kbGVyIGltcGxlbWVudHMgSW5mZXJlbmNlU2Vzc2lvbkhhbmRsZXIge1xuICBwcml2YXRlIHNlc3Npb25JZDogbnVtYmVyO1xuXG4gIGlucHV0TmFtZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuICBvdXRwdXROYW1lczogcmVhZG9ubHkgc3RyaW5nW107XG4gIGlucHV0TWV0YWRhdGE6IHJlYWRvbmx5IEluZmVyZW5jZVNlc3Npb24uVmFsdWVNZXRhZGF0YVtdO1xuICBvdXRwdXRNZXRhZGF0YTogcmVhZG9ubHkgSW5mZXJlbmNlU2Vzc2lvbi5WYWx1ZU1ldGFkYXRhW107XG5cbiAgYXN5bmMgZmV0Y2hNb2RlbEFuZENvcHlUb1dhc21NZW1vcnkocGF0aDogc3RyaW5nKTogUHJvbWlzZTxTZXJpYWxpemFibGVJbnRlcm5hbEJ1ZmZlcj4ge1xuICAgIC8vIGZldGNoIG1vZGVsIGZyb20gdXJsIGFuZCBtb3ZlIHRvIHdhc20gaGVhcC5cbiAgICByZXR1cm4gY29weUZyb21FeHRlcm5hbEJ1ZmZlcihhd2FpdCBsb2FkRmlsZShwYXRoKSk7XG4gIH1cblxuICBhc3luYyBsb2FkTW9kZWwocGF0aE9yQnVmZmVyOiBzdHJpbmcgfCBVaW50OEFycmF5LCBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIFRSQUNFX0ZVTkNfQkVHSU4oKTtcbiAgICBsZXQgbW9kZWw6IFBhcmFtZXRlcnM8dHlwZW9mIGNyZWF0ZVNlc3Npb24+WzBdO1xuXG4gICAgaWYgKHR5cGVvZiBwYXRoT3JCdWZmZXIgPT09ICdzdHJpbmcnKSB7XG4gICAgICBpZiAoaXNOb2RlKSB7XG4gICAgICAgIC8vIG5vZGVcbiAgICAgICAgbW9kZWwgPSBhd2FpdCBsb2FkRmlsZShwYXRoT3JCdWZmZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gYnJvd3NlclxuICAgICAgICAvLyBmZXRjaCBtb2RlbCBhbmQgY29weSB0byB3YXNtIGhlYXAuXG4gICAgICAgIG1vZGVsID0gYXdhaXQgdGhpcy5mZXRjaE1vZGVsQW5kQ29weVRvV2FzbU1lbW9yeShwYXRoT3JCdWZmZXIpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBtb2RlbCA9IHBhdGhPckJ1ZmZlcjtcbiAgICB9XG5cbiAgICBbdGhpcy5zZXNzaW9uSWQsIHRoaXMuaW5wdXROYW1lcywgdGhpcy5vdXRwdXROYW1lcywgdGhpcy5pbnB1dE1ldGFkYXRhLCB0aGlzLm91dHB1dE1ldGFkYXRhXSA9IGF3YWl0IGNyZWF0ZVNlc3Npb24oXG4gICAgICBtb2RlbCxcbiAgICAgIG9wdGlvbnMsXG4gICAgKTtcbiAgICBUUkFDRV9GVU5DX0VORCgpO1xuICB9XG5cbiAgYXN5bmMgZGlzcG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gcmVsZWFzZVNlc3Npb24odGhpcy5zZXNzaW9uSWQpO1xuICB9XG5cbiAgYXN5bmMgcnVuKFxuICAgIGZlZWRzOiBTZXNzaW9uSGFuZGxlci5GZWVkc1R5cGUsXG4gICAgZmV0Y2hlczogU2Vzc2lvbkhhbmRsZXIuRmV0Y2hlc1R5cGUsXG4gICAgb3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5SdW5PcHRpb25zLFxuICApOiBQcm9taXNlPFNlc3Npb25IYW5kbGVyLlJldHVyblR5cGU+IHtcbiAgICBUUkFDRV9GVU5DX0JFR0lOKCk7XG4gICAgY29uc3QgaW5wdXRBcnJheTogVGVuc29yW10gPSBbXTtcbiAgICBjb25zdCBpbnB1dEluZGljZXM6IG51bWJlcltdID0gW107XG4gICAgT2JqZWN0LmVudHJpZXMoZmVlZHMpLmZvckVhY2goKGt2cCkgPT4ge1xuICAgICAgY29uc3QgbmFtZSA9IGt2cFswXTtcbiAgICAgIGNvbnN0IHRlbnNvciA9IGt2cFsxXTtcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5pbnB1dE5hbWVzLmluZGV4T2YobmFtZSk7XG4gICAgICBpZiAoaW5kZXggPT09IC0xKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBpbnB1dCAnJHtuYW1lfSdgKTtcbiAgICAgIH1cbiAgICAgIGlucHV0QXJyYXkucHVzaCh0ZW5zb3IpO1xuICAgICAgaW5wdXRJbmRpY2VzLnB1c2goaW5kZXgpO1xuICAgIH0pO1xuXG4gICAgY29uc3Qgb3V0cHV0QXJyYXk6IEFycmF5PFRlbnNvciB8IG51bGw+ID0gW107XG4gICAgY29uc3Qgb3V0cHV0SW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgICBPYmplY3QuZW50cmllcyhmZXRjaGVzKS5mb3JFYWNoKChrdnApID0+IHtcbiAgICAgIGNvbnN0IG5hbWUgPSBrdnBbMF07XG4gICAgICBjb25zdCB0ZW5zb3IgPSBrdnBbMV07XG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMub3V0cHV0TmFtZXMuaW5kZXhPZihuYW1lKTtcbiAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIG91dHB1dCAnJHtuYW1lfSdgKTtcbiAgICAgIH1cbiAgICAgIG91dHB1dEFycmF5LnB1c2godGVuc29yKTtcbiAgICAgIG91dHB1dEluZGljZXMucHVzaChpbmRleCk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBpbnB1dHMgPSBpbnB1dEFycmF5Lm1hcCgodCwgaSkgPT5cbiAgICAgIGVuY29kZVRlbnNvck1ldGFkYXRhKHQsICgpID0+IGBpbnB1dCBcIiR7dGhpcy5pbnB1dE5hbWVzW2lucHV0SW5kaWNlc1tpXV19XCJgKSxcbiAgICApO1xuICAgIGNvbnN0IG91dHB1dHMgPSBvdXRwdXRBcnJheS5tYXAoKHQsIGkpID0+XG4gICAgICB0ID8gZW5jb2RlVGVuc29yTWV0YWRhdGEodCwgKCkgPT4gYG91dHB1dCBcIiR7dGhpcy5vdXRwdXROYW1lc1tvdXRwdXRJbmRpY2VzW2ldXX1cImApIDogbnVsbCxcbiAgICApO1xuXG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHJ1bih0aGlzLnNlc3Npb25JZCwgaW5wdXRJbmRpY2VzLCBpbnB1dHMsIG91dHB1dEluZGljZXMsIG91dHB1dHMsIG9wdGlvbnMpO1xuXG4gICAgY29uc3QgcmVzdWx0TWFwOiBTZXNzaW9uSGFuZGxlci5SZXR1cm5UeXBlID0ge307XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXN1bHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICByZXN1bHRNYXBbdGhpcy5vdXRwdXROYW1lc1tvdXRwdXRJbmRpY2VzW2ldXV0gPSBvdXRwdXRBcnJheVtpXSA/PyBkZWNvZGVUZW5zb3JNZXRhZGF0YShyZXN1bHRzW2ldKTtcbiAgICB9XG4gICAgVFJBQ0VfRlVOQ19FTkQoKTtcbiAgICByZXR1cm4gcmVzdWx0TWFwO1xuICB9XG5cbiAgc3RhcnRQcm9maWxpbmcoKTogdm9pZCB7XG4gICAgLy8gVE9ETzogaW1wbGVtZW50IHByb2ZpbGluZ1xuICB9XG5cbiAgZW5kUHJvZmlsaW5nKCk6IHZvaWQge1xuICAgIHZvaWQgZW5kUHJvZmlsaW5nKHRoaXMuc2Vzc2lvbklkKTtcbiAgfVxufVxuIiwgIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgeyBCYWNrZW5kLCBlbnYsIEluZmVyZW5jZVNlc3Npb24sIEluZmVyZW5jZVNlc3Npb25IYW5kbGVyIH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHsgaW5pdGlhbGl6ZU9ydEVwLCBpbml0aWFsaXplV2ViQXNzZW1ibHlBbmRPcnRSdW50aW1lIH0gZnJvbSAnLi93YXNtL3Byb3h5LXdyYXBwZXInO1xuaW1wb3J0IHsgT25ueHJ1bnRpbWVXZWJBc3NlbWJseVNlc3Npb25IYW5kbGVyIH0gZnJvbSAnLi93YXNtL3Nlc3Npb24taGFuZGxlci1pbmZlcmVuY2UnO1xuXG4vKipcbiAqIFRoaXMgZnVuY3Rpb24gaW5pdGlhbGl6ZXMgYWxsIGZsYWdzIGZvciBXZWJBc3NlbWJseS5cbiAqXG4gKiBUaG9zZSBmbGFncyBhcmUgYWNjZXNzaWJsZSBmcm9tIGBvcnQuZW52Lndhc21gLiBVc2VycyBhcmUgYWxsb3cgdG8gc2V0IHRob3NlIGZsYWdzIGJlZm9yZSB0aGUgZmlyc3QgaW5mZXJlbmNlIHNlc3Npb25cbiAqIGJlaW5nIGNyZWF0ZWQsIHRvIG92ZXJyaWRlIGRlZmF1bHQgdmFsdWUuXG4gKi9cbmV4cG9ydCBjb25zdCBpbml0aWFsaXplRmxhZ3MgPSAoKTogdm9pZCA9PiB7XG4gIGlmICh0eXBlb2YgZW52Lndhc20uaW5pdFRpbWVvdXQgIT09ICdudW1iZXInIHx8IGVudi53YXNtLmluaXRUaW1lb3V0IDwgMCkge1xuICAgIGVudi53YXNtLmluaXRUaW1lb3V0ID0gMDtcbiAgfVxuXG4gIGNvbnN0IHNpbWQgPSBlbnYud2FzbS5zaW1kO1xuICBpZiAodHlwZW9mIHNpbWQgIT09ICdib29sZWFuJyAmJiBzaW1kICE9PSB1bmRlZmluZWQgJiYgc2ltZCAhPT0gJ2ZpeGVkJyAmJiBzaW1kICE9PSAncmVsYXhlZCcpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgIGNvbnNvbGUud2FybihcbiAgICAgIGBQcm9wZXJ0eSBcImVudi53YXNtLnNpbWRcIiBpcyBzZXQgdG8gdW5rbm93biB2YWx1ZSBcIiR7c2ltZH1cIi4gUmVzZXQgaXQgdG8gXFxgZmFsc2VcXGAgYW5kIGlnbm9yZSBTSU1EIGZlYXR1cmUgY2hlY2tpbmcuYCxcbiAgICApO1xuICAgIGVudi53YXNtLnNpbWQgPSBmYWxzZTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgZW52Lndhc20ucHJveHkgIT09ICdib29sZWFuJykge1xuICAgIGVudi53YXNtLnByb3h5ID0gZmFsc2U7XG4gIH1cblxuICBpZiAodHlwZW9mIGVudi53YXNtLnRyYWNlICE9PSAnYm9vbGVhbicpIHtcbiAgICBlbnYud2FzbS50cmFjZSA9IGZhbHNlO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBlbnYud2FzbS5udW1UaHJlYWRzICE9PSAnbnVtYmVyJyB8fCAhTnVtYmVyLmlzSW50ZWdlcihlbnYud2FzbS5udW1UaHJlYWRzKSB8fCBlbnYud2FzbS5udW1UaHJlYWRzIDw9IDApIHtcbiAgICAvLyBUaGUgZm9sbG93aW5nIGxvZ2ljIG9ubHkgYXBwbGllcyB3aGVuIGBvcnQuZW52Lndhc20ubnVtVGhyZWFkc2AgaXMgbm90IHNldCBieSB1c2VyLiBXZSB3aWxsIGFsd2F5cyBob25vciB1c2VyJ3NcbiAgICAvLyBzZXR0aW5nIGlmIGl0IGlzIHByb3ZpZGVkLlxuXG4gICAgLy8gQnJvd3Nlcjogd2hlbiBjcm9zc09yaWdpbklzb2xhdGVkIGlzIGZhbHNlLCBTaGFyZWRBcnJheUJ1ZmZlciBpcyBub3QgYXZhaWxhYmxlIHNvIFdlYkFzc2VtYmx5IHRocmVhZHMgd2lsbCBub3RcbiAgICAvLyB3b3JrLiBJbiB0aGlzIGNhc2UsIHdlIHdpbGwgc2V0IG51bVRocmVhZHMgdG8gMS5cbiAgICAvL1xuICAgIC8vIFRoZXJlIGlzIGFuIGV4Y2VwdGlvbjogd2hlbiB0aGUgYnJvd3NlciBpcyBjb25maWd1cmVkIHRvIGZvcmNlLWVuYWJsZSBTaGFyZWRBcnJheUJ1ZmZlciAoZS5nLiBDaHJvbXVpbSB3aXRoXG4gICAgLy8gLS1lbmFibGUtZmVhdHVyZXM9U2hhcmVkQXJyYXlCdWZmZXIpLCBpdCBpcyBwb3NzaWJsZSB0aGF0IGBzZWxmLmNyb3NzT3JpZ2luSXNvbGF0ZWRgIGlzIGZhbHNlIGFuZFxuICAgIC8vIFNoYXJlZEFycmF5QnVmZmVyIGlzIGF2YWlsYWJsZSBhdCB0aGUgc2FtZSB0aW1lLiBUaGlzIGlzIHVzdWFsbHkgZm9yIHRlc3RpbmcuIEluIHRoaXMgY2FzZSwgIHdlIHdpbGwgc3RpbGwgc2V0XG4gICAgLy8gbnVtVGhyZWFkcyB0byAxIGhlcmUuIElmIHdlIHdhbnQgdG8gZW5hYmxlIG11bHRpLXRocmVhZGluZyBpbiB0ZXN0LCB3ZSBzaG91bGQgc2V0IGBvcnQuZW52Lndhc20ubnVtVGhyZWFkc2AgdG8gYVxuICAgIC8vIHZhbHVlIGdyZWF0ZXIgdGhhbiAxLlxuICAgIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcgJiYgIXNlbGYuY3Jvc3NPcmlnaW5Jc29sYXRlZCkge1xuICAgICAgZW52Lndhc20ubnVtVGhyZWFkcyA9IDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG51bUNwdUxvZ2ljYWxDb3JlcyA9XG4gICAgICAgIHR5cGVvZiBuYXZpZ2F0b3IgPT09ICd1bmRlZmluZWQnID8gcmVxdWlyZSgnbm9kZTpvcycpLmNwdXMoKS5sZW5ndGggOiBuYXZpZ2F0b3IuaGFyZHdhcmVDb25jdXJyZW5jeTtcbiAgICAgIGVudi53YXNtLm51bVRocmVhZHMgPSBNYXRoLm1pbig0LCBNYXRoLmNlaWwoKG51bUNwdUxvZ2ljYWxDb3JlcyB8fCAxKSAvIDIpKTtcbiAgICB9XG4gIH1cbn07XG5cbmV4cG9ydCBjbGFzcyBPbm54cnVudGltZVdlYkFzc2VtYmx5QmFja2VuZCBpbXBsZW1lbnRzIEJhY2tlbmQge1xuICAvKipcbiAgICogVGhpcyBmdW5jdGlvbiBpbml0aWFsaXplcyB0aGUgV2ViQXNzZW1ibHkgYmFja2VuZC5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBvbmx5IG9uY2UgZm9yIGVhY2ggYmFja2VuZCBuYW1lLiBJdCB3aWxsIGJlIGNhbGxlZCB0aGUgZmlyc3QgdGltZSB3aGVuXG4gICAqIGBvcnQuSW5mZXJlbmNlU2Vzc2lvbi5jcmVhdGUoKWAgaXMgY2FsbGVkIHdpdGggYSByZWdpc3RlcmVkIGJhY2tlbmQgbmFtZS5cbiAgICpcbiAgICogQHBhcmFtIGJhY2tlbmROYW1lIC0gdGhlIHJlZ2lzdGVyZWQgYmFja2VuZCBuYW1lLlxuICAgKi9cbiAgYXN5bmMgaW5pdChiYWNrZW5kTmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gcG9wdWxhdGUgd2FzbSBmbGFnc1xuICAgIGluaXRpYWxpemVGbGFncygpO1xuXG4gICAgLy8gaW5pdCB3YXNtXG4gICAgYXdhaXQgaW5pdGlhbGl6ZVdlYkFzc2VtYmx5QW5kT3J0UnVudGltZSgpO1xuXG4gICAgLy8gcGVyZm9ybWUgRVAgc3BlY2lmaWMgaW5pdGlhbGl6YXRpb25cbiAgICBhd2FpdCBpbml0aWFsaXplT3J0RXAoYmFja2VuZE5hbWUpO1xuICB9XG4gIGNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uSGFuZGxlcj47XG4gIGNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKFxuICAgIGJ1ZmZlcjogVWludDhBcnJheSxcbiAgICBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uSGFuZGxlcj47XG4gIGFzeW5jIGNyZWF0ZUluZmVyZW5jZVNlc3Npb25IYW5kbGVyKFxuICAgIHBhdGhPckJ1ZmZlcjogc3RyaW5nIHwgVWludDhBcnJheSxcbiAgICBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxJbmZlcmVuY2VTZXNzaW9uSGFuZGxlcj4ge1xuICAgIGNvbnN0IGhhbmRsZXIgPSBuZXcgT25ueHJ1bnRpbWVXZWJBc3NlbWJseVNlc3Npb25IYW5kbGVyKCk7XG4gICAgYXdhaXQgaGFuZGxlci5sb2FkTW9kZWwocGF0aE9yQnVmZmVyLCBvcHRpb25zKTtcbiAgICByZXR1cm4gaGFuZGxlcjtcbiAgfVxufVxuXG5leHBvcnQgY29uc3Qgd2FzbUJhY2tlbmQgPSBuZXcgT25ueHJ1bnRpbWVXZWJBc3NlbWJseUJhY2tlbmQoKTtcbiIsICIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlcywgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAqL1xuXG4vLyBXZSB1c2UgXCJyZXF1aXJlXCIgaW5zdGVhZCBvZiBcImltcG9ydFwiIGhlcmUgYmVjYXVzZSBpbXBvcnQgc3RhdGVtZW50IG11c3QgYmUgcHV0IGluIHRvcCBsZXZlbC4gT3VyIGN1cnJlbnQgY29kZSBkb2VzXG4vLyBub3QgYWxsb3cgYnVuZGxlciB0byB0cmVlLXNoYWtpbmcgY29kZSBhcyBleHBlY3RlZCBiZWNhdXNlIHNvbWUgY29kZXMgYXJlIHRyZWF0ZWQgYXMgaGF2aW5nIHNpZGUgZWZmZWN0cy5cbi8vIFNvIHdlIGltcG9ydCBjb2RlIGluc2lkZSB0aGUgaWYtY2xhdXNlIHRvIGFsbG93IGJ1bmRsZXIgcmVtb3ZlIHRoZSBjb2RlIHNhZmVseS5cblxuZXhwb3J0ICogZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcbmltcG9ydCAqIGFzIG9ydCBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuZXhwb3J0IGRlZmF1bHQgb3J0O1xuXG5pbXBvcnQgeyByZWdpc3RlckJhY2tlbmQsIGVudiB9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5pbXBvcnQgeyB2ZXJzaW9uIH0gZnJvbSAnLi92ZXJzaW9uJztcblxuaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0VCR0wpIHtcbiAgY29uc3Qgb25ueGpzQmFja2VuZCA9IHJlcXVpcmUoJy4vYmFja2VuZC1vbm54anMnKS5vbm54anNCYWNrZW5kO1xuICByZWdpc3RlckJhY2tlbmQoJ3dlYmdsJywgb25ueGpzQmFja2VuZCwgLTEwKTtcbn1cblxuaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTSkge1xuICBjb25zdCB3YXNtQmFja2VuZCA9IHJlcXVpcmUoJy4vYmFja2VuZC13YXNtJykud2FzbUJhY2tlbmQ7XG4gIGlmICghQlVJTERfREVGUy5ESVNBQkxFX0pTRVApIHtcbiAgICByZWdpc3RlckJhY2tlbmQoJ3dlYmdwdScsIHdhc21CYWNrZW5kLCA1KTtcbiAgICByZWdpc3RlckJhY2tlbmQoJ3dlYm5uJywgd2FzbUJhY2tlbmQsIDUpO1xuICB9XG4gIHJlZ2lzdGVyQmFja2VuZCgnY3B1Jywgd2FzbUJhY2tlbmQsIDEwKTtcbiAgcmVnaXN0ZXJCYWNrZW5kKCd3YXNtJywgd2FzbUJhY2tlbmQsIDEwKTtcbn1cblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGVudi52ZXJzaW9ucywgJ3dlYicsIHsgdmFsdWU6IHZlcnNpb24sIGVudW1lcmFibGU6IHRydWUgfSk7XG4iLCAiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbi8vIFRoaXMgZmlsZSBpcyBnZW5lcmF0ZWQgYnkgL2pzL3NjcmlwdHMvdXBkYXRlLXZlcnNpb24udHNcbi8vIERvIG5vdCBtb2RpZnkgZmlsZSBjb250ZW50IG1hbnVhbGx5LlxuXG5leHBvcnQgY29uc3QgdmVyc2lvbiA9ICcxLjIzLjAnO1xuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxNQWdCTSxVQUNBLDBCQVlPLGlCQXdDUCxnQ0F3Q087QUE3R2I7OztBQWdCQSxNQUFNLFdBQXFDLG9CQUFJLElBQUc7QUFDbEQsTUFBTSwyQkFBcUMsQ0FBQTtBQVlwQyxNQUFNLGtCQUFrQixDQUFDLE1BQWMsU0FBa0IsYUFBMEI7QUFDeEYsWUFBSSxXQUFXLE9BQU8sUUFBUSxTQUFTLGNBQWMsT0FBTyxRQUFRLGtDQUFrQyxZQUFZO0FBQ2hILGdCQUFNLGlCQUFpQixTQUFTLElBQUksSUFBSTtBQUN4QyxjQUFJLG1CQUFtQixRQUFXO0FBQ2hDLHFCQUFTLElBQUksTUFBTSxFQUFFLFNBQVMsU0FBUSxDQUFFO3FCQUMvQixlQUFlLFdBQVcsVUFBVTtBQUU3QztxQkFDUyxlQUFlLGFBQWEsVUFBVTtBQUMvQyxnQkFBSSxlQUFlLFlBQVksU0FBUztBQUN0QyxvQkFBTSxJQUFJLE1BQU0sNEJBQTRCLElBQUksb0JBQW9CLFFBQVEsRUFBRTs7O0FBSWxGLGNBQUksWUFBWSxHQUFHO0FBQ2pCLGtCQUFNLElBQUkseUJBQXlCLFFBQVEsSUFBSTtBQUMvQyxnQkFBSSxNQUFNLElBQUk7QUFDWix1Q0FBeUIsT0FBTyxHQUFHLENBQUM7O0FBR3RDLHFCQUFTQSxLQUFJLEdBQUdBLEtBQUkseUJBQXlCLFFBQVFBLE1BQUs7QUFDeEQsa0JBQUksU0FBUyxJQUFJLHlCQUF5QkEsRUFBQyxDQUFDLEVBQUcsWUFBWSxVQUFVO0FBQ25FLHlDQUF5QixPQUFPQSxJQUFHLEdBQUcsSUFBSTtBQUMxQzs7O0FBR0oscUNBQXlCLEtBQUssSUFBSTs7QUFFcEM7O0FBR0YsY0FBTSxJQUFJLFVBQVUscUJBQXFCO01BQzNDO0FBUUEsTUFBTSxpQ0FBaUMsT0FBTyxnQkFBa0Q7QUFDOUYsY0FBTSxjQUFjLFNBQVMsSUFBSSxXQUFXO0FBQzVDLFlBQUksQ0FBQyxhQUFhO0FBQ2hCLGlCQUFPOztBQUdULFlBQUksWUFBWSxhQUFhO0FBQzNCLGlCQUFPLFlBQVk7bUJBQ1YsWUFBWSxTQUFTO0FBQzlCLGlCQUFPLFlBQVk7ZUFDZDtBQUNMLGdCQUFNLGlCQUFpQixDQUFDLENBQUMsWUFBWTtBQUNyQyxjQUFJO0FBQ0YsZ0JBQUksQ0FBQyxnQkFBZ0I7QUFDbkIsMEJBQVksY0FBYyxZQUFZLFFBQVEsS0FBSyxXQUFXOztBQUVoRSxrQkFBTSxZQUFZO0FBQ2xCLHdCQUFZLGNBQWM7QUFDMUIsbUJBQU8sWUFBWTttQkFDWixHQUFHO0FBQ1YsZ0JBQUksQ0FBQyxnQkFBZ0I7QUFDbkIsMEJBQVksUUFBUSxHQUFHLENBQUM7QUFDeEIsMEJBQVksVUFBVTs7QUFFeEIsbUJBQU8sWUFBWTs7QUFFbkIsbUJBQU8sWUFBWTs7O01BR3pCO0FBV08sTUFBTSxzQ0FBc0MsT0FDakQsWUFDeUU7QUFFekUsY0FBTSxNQUFNLFFBQVEsc0JBQXNCLENBQUE7QUFDMUMsY0FBTSxlQUFlLElBQUksSUFBSSxDQUFDLE1BQU8sT0FBTyxNQUFNLFdBQVcsSUFBSSxFQUFFLElBQUs7QUFDeEUsY0FBTSxlQUFlLGFBQWEsV0FBVyxJQUFJLDJCQUEyQjtBQUc1RSxZQUFJO0FBQ0osY0FBTSxTQUFTLENBQUE7QUFDZixjQUFNLHdCQUF3QixvQkFBSSxJQUFHO0FBQ3JDLG1CQUFXLGVBQWUsY0FBYztBQUN0QyxnQkFBTSxnQkFBZ0IsTUFBTSwrQkFBK0IsV0FBVztBQUN0RSxjQUFJLE9BQU8sa0JBQWtCLFVBQVU7QUFDckMsbUJBQU8sS0FBSyxFQUFFLE1BQU0sYUFBYSxLQUFLLGNBQWEsQ0FBRTtpQkFDaEQ7QUFDTCxnQkFBSSxDQUFDLFNBQVM7QUFDWix3QkFBVTs7QUFFWixnQkFBSSxZQUFZLGVBQWU7QUFDN0Isb0NBQXNCLElBQUksV0FBVzs7OztBQU0zQyxZQUFJLENBQUMsU0FBUztBQUNaLGdCQUFNLElBQUksTUFBTSxvQ0FBb0MsT0FBTyxJQUFJLENBQUMsTUFBTSxJQUFJLEVBQUUsSUFBSSxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUUsS0FBSyxJQUFJLENBQUMsRUFBRTs7QUFJNUcsbUJBQVcsRUFBRSxNQUFNLElBQUcsS0FBTSxRQUFRO0FBQ2xDLGNBQUksYUFBYSxTQUFTLElBQUksR0FBRztBQUUvQixvQkFBUSxLQUNOLDBDQUEwQyxJQUFJLHVEQUF1RCxHQUFHLEVBQUU7OztBQUtoSCxjQUFNLGNBQWMsSUFBSSxPQUFPLENBQUMsTUFBTSxzQkFBc0IsSUFBSSxPQUFPLE1BQU0sV0FBVyxJQUFJLEVBQUUsSUFBSSxDQUFDO0FBRW5HLGVBQU87VUFDTDtVQUNBLElBQUksTUFBTSxTQUFTO1lBQ2pCLEtBQUssQ0FBQyxRQUFRLFNBQVE7QUFDcEIsa0JBQUksU0FBUyxzQkFBc0I7QUFDakMsdUJBQU87O0FBRVQscUJBQU8sUUFBUSxJQUFJLFFBQVEsSUFBSTtZQUNqQztXQUNEOztNQUVMOzs7OztBQ25LQTs7O0FBK0RBOzs7OztBQy9EQSxNQU1hO0FBTmI7OztBQU1PLE1BQU0sVUFBVTs7Ozs7QUNOdkIsTUFRSSxlQUVTO0FBVmI7OztBQUlBO0FBSUEsTUFBSSxnQkFBd0M7QUFFckMsTUFBTSxNQUFXO1FBQ3RCLE1BQU0sQ0FBQTtRQUNOLE9BQU8sQ0FBQTtRQUNQLFFBQVEsQ0FBQTtRQUNSLFVBQVUsRUFBRSxRQUFRLFFBQU87UUFFM0IsSUFBSSxTQUFTLE9BQW1CO0FBQzlCLGNBQUksVUFBVSxRQUFXO0FBQ3ZCOztBQUVGLGNBQUksT0FBTyxVQUFVLFlBQVksQ0FBQyxXQUFXLFFBQVEsV0FBVyxTQUFTLE9BQU8sRUFBRSxRQUFRLEtBQUssTUFBTSxJQUFJO0FBQ3ZHLGtCQUFNLElBQUksTUFBTSw4QkFBOEIsS0FBSyxFQUFFOztBQUV2RCwwQkFBZ0I7UUFDbEI7UUFDQSxJQUFJLFdBQVE7QUFDVixpQkFBTztRQUNUOztBQUlGLGFBQU8sZUFBZSxLQUFLLFlBQVksRUFBRSxZQUFZLEtBQUksQ0FBRTs7Ozs7QUMvQjNELE1BeVNhQztBQXpTYjs7O0FBR0E7QUFzU08sTUFBTUEsT0FBVzs7Ozs7QUN6U3hCLE1BU2EsaUJBbUdBO0FBNUdiOzs7QUFTTyxNQUFNLGtCQUFrQixDQUFDLFFBQWdCLFlBQTRDO0FBQzFGLGNBQU0sU0FBUyxPQUFPLGFBQWEsY0FBYyxTQUFTLGNBQWMsUUFBUSxJQUFJLElBQUksZ0JBQWdCLEdBQUcsQ0FBQztBQUM1RyxlQUFPLFFBQVEsT0FBTyxLQUFLLENBQUM7QUFDNUIsZUFBTyxTQUFTLE9BQU8sS0FBSyxDQUFDO0FBQzdCLGNBQU0sa0JBQWtCLE9BQU8sV0FBVyxJQUFJO0FBSzlDLFlBQUksbUJBQW1CLE1BQU07QUFFM0IsY0FBSTtBQUNKLGNBQUk7QUFDSixjQUFJLFNBQVMsaUJBQWlCLFVBQWEsUUFBUSxpQkFBaUIsUUFBUTtBQUMxRSxvQkFBUSxPQUFPLEtBQUssQ0FBQztBQUNyQixxQkFBUyxPQUFPLEtBQUssQ0FBQztpQkFDakI7QUFFTCxvQkFBUSxPQUFPLEtBQUssQ0FBQztBQUNyQixxQkFBUyxPQUFPLEtBQUssQ0FBQzs7QUFHeEIsZ0JBQU0sY0FBYyxTQUFTLFdBQVcsU0FBWSxRQUFRLFNBQVM7QUFFckUsZ0JBQU0sT0FBTyxTQUFTO0FBQ3RCLGNBQUk7QUFDSixjQUFJO0FBQ0osY0FBSSxTQUFTLFVBQWEsS0FBSyxTQUFTLFFBQVc7QUFDakQsdUJBQVcsQ0FBQyxLQUFLLEtBQUssS0FBSyxHQUFHO2lCQUN6QjtBQUNMLGdCQUFJLE9BQU8sS0FBSyxTQUFTLFVBQVU7QUFDakMseUJBQVcsQ0FBQyxLQUFLLE1BQU0sS0FBSyxNQUFNLEtBQUssTUFBTSxLQUFLLElBQUk7bUJBQ2pEO0FBQ0wseUJBQVcsQ0FBQyxLQUFLLEtBQUssQ0FBQyxHQUFHLEtBQUssS0FBSyxDQUFDLEdBQUcsS0FBSyxLQUFLLENBQUMsR0FBRyxDQUFDO0FBQ3ZELGtCQUFJLEtBQUssS0FBSyxDQUFDLE1BQU0sUUFBVztBQUM5Qix5QkFBUyxDQUFDLElBQUksS0FBSyxLQUFLLENBQUM7Ozs7QUFJL0IsY0FBSSxTQUFTLFVBQWEsS0FBSyxTQUFTLFFBQVc7QUFDakQsdUJBQVcsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO2lCQUNqQjtBQUNMLGdCQUFJLE9BQU8sS0FBSyxTQUFTLFVBQVU7QUFDakMseUJBQVcsQ0FBQyxLQUFLLE1BQU0sS0FBSyxNQUFNLEtBQUssTUFBTSxLQUFLLElBQUk7bUJBQ2pEO0FBQ0wseUJBQVcsQ0FBQyxLQUFLLEtBQUssQ0FBQyxHQUFHLEtBQUssS0FBSyxDQUFDLEdBQUcsS0FBSyxLQUFLLENBQUMsR0FBRyxDQUFDO0FBQ3ZELGtCQUFJLEtBQUssS0FBSyxDQUFDLE1BQU0sUUFBVztBQUM5Qix5QkFBUyxDQUFDLElBQUksS0FBSyxLQUFLLENBQUM7Ozs7QUFLL0IsZ0JBQU0sU0FBUyxTQUFTO0FBRXhCLGNBQUksaUJBQWlCLEdBQ25CLGlCQUFpQixRQUNqQixpQkFBaUIsU0FBUyxHQUMxQixpQkFBaUI7QUFHbkIsY0FBSSxnQkFBZ0IsUUFBUTtBQUMxQiw2QkFBaUI7QUFDakIsNkJBQWlCO0FBQ2pCLDZCQUFpQixTQUFTO0FBQzFCLDZCQUFpQixTQUFTO3FCQUNqQixnQkFBZ0IsT0FBTztBQUNoQyw2QkFBaUI7QUFDakIsNkJBQWlCO0FBQ2pCLDZCQUFpQixTQUFTO3FCQUNqQixnQkFBZ0IsT0FBTztBQUNoQyw2QkFBaUI7QUFDakIsNkJBQWlCO0FBQ2pCLDZCQUFpQixTQUFTOztBQUc1QixtQkFBUyxJQUFJLEdBQUcsSUFBSSxRQUFRLEtBQUs7QUFDL0IscUJBQVMsSUFBSSxHQUFHLElBQUksT0FBTyxLQUFLO0FBQzlCLG9CQUFNLEtBQU0sT0FBTyxLQUFLLGdCQUFnQixJQUFlLFNBQVMsQ0FBQyxLQUFLLFNBQVMsQ0FBQztBQUNoRixvQkFBTSxLQUFNLE9BQU8sS0FBSyxnQkFBZ0IsSUFBZSxTQUFTLENBQUMsS0FBSyxTQUFTLENBQUM7QUFDaEYsb0JBQU0sS0FBTSxPQUFPLEtBQUssZ0JBQWdCLElBQWUsU0FBUyxDQUFDLEtBQUssU0FBUyxDQUFDO0FBQ2hGLG9CQUFNLElBQUksbUJBQW1CLEtBQUssT0FBUSxPQUFPLEtBQUssZ0JBQWdCLElBQWUsU0FBUyxDQUFDLEtBQUssU0FBUyxDQUFDO0FBRTlHLDhCQUFnQixZQUFZLFVBQVUsSUFBSSxNQUFNLElBQUksTUFBTSxJQUFJLE1BQU0sSUFBSTtBQUN4RSw4QkFBZ0IsU0FBUyxHQUFHLEdBQUcsR0FBRyxDQUFDOzs7QUFHdkMsY0FBSSxlQUFlLFFBQVE7QUFDekIsbUJBQU8sT0FBTyxVQUFTO2lCQUNsQjtBQUNMLGtCQUFNLElBQUksTUFBTSw0QkFBNEI7O2VBRXpDO0FBQ0wsZ0JBQU0sSUFBSSxNQUFNLDJCQUEyQjs7TUFFL0M7QUFLTyxNQUFNLG9CQUFvQixDQUFDLFFBQWdCLFlBQWlEO0FBQ2pHLGNBQU0sa0JBQ0osT0FBTyxhQUFhLGNBQ2hCLFNBQVMsY0FBYyxRQUFRLEVBQUUsV0FBVyxJQUFJLElBQy9DLElBQUksZ0JBQWdCLEdBQUcsQ0FBQyxFQUFFLFdBQVcsSUFBSTtBQUNoRCxZQUFJO0FBQ0osWUFBSSxtQkFBbUIsTUFBTTtBQUUzQixjQUFJO0FBQ0osY0FBSTtBQUNKLGNBQUk7QUFDSixjQUFJLFNBQVMsaUJBQWlCLFVBQWEsUUFBUSxpQkFBaUIsUUFBUTtBQUMxRSxvQkFBUSxPQUFPLEtBQUssQ0FBQztBQUNyQixxQkFBUyxPQUFPLEtBQUssQ0FBQztBQUN0Qix1QkFBVyxPQUFPLEtBQUssQ0FBQztpQkFDbkI7QUFFTCxvQkFBUSxPQUFPLEtBQUssQ0FBQztBQUNyQixxQkFBUyxPQUFPLEtBQUssQ0FBQztBQUN0Qix1QkFBVyxPQUFPLEtBQUssQ0FBQzs7QUFFMUIsZ0JBQU0sY0FBYyxZQUFZLFNBQWEsUUFBUSxXQUFXLFNBQVksUUFBUSxTQUFTLFFBQVM7QUFFdEcsZ0JBQU0sT0FBTyxTQUFTO0FBQ3RCLGNBQUk7QUFDSixjQUFJO0FBQ0osY0FBSSxTQUFTLFVBQWEsS0FBSyxTQUFTLFFBQVc7QUFDakQsdUJBQVcsQ0FBQyxLQUFLLEtBQUssS0FBSyxHQUFHO2lCQUN6QjtBQUNMLGdCQUFJLE9BQU8sS0FBSyxTQUFTLFVBQVU7QUFDakMseUJBQVcsQ0FBQyxLQUFLLE1BQU0sS0FBSyxNQUFNLEtBQUssTUFBTSxLQUFLLElBQUk7bUJBQ2pEO0FBQ0wseUJBQVcsQ0FBQyxLQUFLLEtBQUssQ0FBQyxHQUFHLEtBQUssS0FBSyxDQUFDLEdBQUcsS0FBSyxLQUFLLENBQUMsR0FBRyxHQUFHO0FBQ3pELGtCQUFJLEtBQUssS0FBSyxDQUFDLE1BQU0sUUFBVztBQUM5Qix5QkFBUyxDQUFDLElBQUksS0FBSyxLQUFLLENBQUM7Ozs7QUFJL0IsY0FBSSxTQUFTLFVBQWEsS0FBSyxTQUFTLFFBQVc7QUFDakQsdUJBQVcsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO2lCQUNqQjtBQUNMLGdCQUFJLE9BQU8sS0FBSyxTQUFTLFVBQVU7QUFDakMseUJBQVcsQ0FBQyxLQUFLLE1BQU0sS0FBSyxNQUFNLEtBQUssTUFBTSxLQUFLLElBQUk7bUJBQ2pEO0FBQ0wseUJBQVcsQ0FBQyxLQUFLLEtBQUssQ0FBQyxHQUFHLEtBQUssS0FBSyxDQUFDLEdBQUcsS0FBSyxLQUFLLENBQUMsR0FBRyxDQUFDO0FBQ3ZELGtCQUFJLEtBQUssS0FBSyxDQUFDLE1BQU0sUUFBVztBQUM5Qix5QkFBUyxDQUFDLElBQUksS0FBSyxLQUFLLENBQUM7Ozs7QUFLL0IsZ0JBQU0sU0FBUyxTQUFTO0FBQ3hCLGNBQUksWUFBWSxRQUFXO0FBQ3pCLGdCQUNHLFFBQVEsV0FBVyxVQUFhLGFBQWEsS0FBSyxRQUFRLFdBQVcsVUFDckUsYUFBYSxLQUFLLFFBQVEsV0FBVyxTQUFTLFFBQVEsV0FBVyxPQUNsRTtBQUNBLG9CQUFNLElBQUksTUFBTSwrQ0FBK0M7OztBQUtuRSxnQkFBTSxPQUFPO0FBQ2IsY0FBSSxnQkFBZ0IsR0FDbEIsZ0JBQWdCLEdBQ2hCLGdCQUFnQixHQUNoQixnQkFBZ0I7QUFDbEIsY0FBSSxpQkFBaUIsR0FDbkIsaUJBQWlCLFFBQ2pCLGlCQUFpQixTQUFTLEdBQzFCLGlCQUFpQjtBQUduQixjQUFJLGdCQUFnQixRQUFRO0FBQzFCLDZCQUFpQjtBQUNqQiw2QkFBaUI7QUFDakIsNkJBQWlCLFNBQVM7QUFDMUIsNkJBQWlCLFNBQVM7cUJBQ2pCLGdCQUFnQixPQUFPO0FBQ2hDLDZCQUFpQjtBQUNqQiw2QkFBaUI7QUFDakIsNkJBQWlCLFNBQVM7cUJBQ2pCLGdCQUFnQixPQUFPO0FBQ2hDLDZCQUFpQjtBQUNqQiw2QkFBaUI7QUFDakIsNkJBQWlCLFNBQVM7O0FBRzVCLGtCQUFRLGdCQUFnQixnQkFBZ0IsT0FBTyxNQUFNO0FBRXJELG1CQUNNLElBQUksR0FDUixJQUFJLFNBQVMsT0FDYixpQkFBaUIsTUFBTSxpQkFBaUIsTUFBTSxpQkFBaUIsTUFBTSxpQkFBaUIsTUFBTSxLQUM1RjtBQUNBLGtCQUFNLEtBQUssYUFBYSxLQUFNLE9BQU8sS0FBSyxnQkFBZ0IsSUFBZSxTQUFTLENBQUMsS0FBSyxTQUFTLENBQUM7QUFDbEcsa0JBQU0sS0FBSyxhQUFhLEtBQU0sT0FBTyxLQUFLLGdCQUFnQixJQUFlLFNBQVMsQ0FBQyxLQUFLLFNBQVMsQ0FBQztBQUNsRyxrQkFBTSxLQUFLLGFBQWEsS0FBTSxPQUFPLEtBQUssZ0JBQWdCLElBQWUsU0FBUyxDQUFDLEtBQUssU0FBUyxDQUFDO0FBQ2xHLGtCQUFNLEtBQUssYUFBYSxJQUN0QixtQkFBbUIsS0FBSyxPQUFRLE9BQU8sS0FBSyxnQkFBZ0IsSUFBZSxTQUFTLENBQUMsS0FBSyxTQUFTLENBQUM7O2VBRW5HO0FBQ0wsZ0JBQU0sSUFBSSxNQUFNLDJCQUEyQjs7QUFFN0MsZUFBTztNQUNUOzs7OztBQ3JOQSxNQWtDYSxnQkE4RkEsaUJBb0tBLG1CQWFBLHFCQVdBLG9CQVdBO0FBdlViOzs7QUFpQkE7QUFpQk8sTUFBTSxpQkFBaUIsQ0FBQyxRQUF1QyxZQUEwQztBQUM5RyxZQUFJLFdBQVcsUUFBVztBQUN4QixnQkFBTSxJQUFJLE1BQU0sOEJBQThCOztBQUVoRCxZQUFJLFFBQVEsV0FBVyxVQUFhLFFBQVEsVUFBVSxRQUFXO0FBQy9ELGdCQUFNLElBQUksTUFBTSx3Q0FBd0M7O0FBRTFELFlBQUksUUFBUSxpQkFBaUIsUUFBUTtBQUNuQyxnQkFBTSxJQUFJLE1BQU0seUNBQXlDOztBQUczRCxjQUFNLEVBQUUsUUFBUSxNQUFLLElBQUs7QUFFMUIsY0FBTSxPQUFPLFFBQVEsUUFBUSxFQUFFLE1BQU0sS0FBSyxNQUFNLEVBQUM7QUFDakQsWUFBSTtBQUNKLFlBQUk7QUFFSixZQUFJLE9BQU8sS0FBSyxTQUFTLFVBQVU7QUFDakMscUJBQVcsQ0FBQyxLQUFLLE1BQU0sS0FBSyxNQUFNLEtBQUssTUFBTSxLQUFLLElBQUk7ZUFDakQ7QUFDTCxxQkFBVyxDQUFDLEtBQUssS0FBTSxDQUFDLEdBQUcsS0FBSyxLQUFNLENBQUMsR0FBRyxLQUFLLEtBQU0sQ0FBQyxHQUFHLEtBQUssS0FBTSxDQUFDLEtBQUssR0FBRzs7QUFHL0UsWUFBSSxPQUFPLEtBQUssU0FBUyxVQUFVO0FBQ2pDLHFCQUFXLENBQUMsS0FBSyxNQUFNLEtBQUssTUFBTSxLQUFLLE1BQU0sS0FBSyxJQUFJO2VBQ2pEO0FBQ0wscUJBQVcsQ0FBQyxLQUFLLEtBQU0sQ0FBQyxHQUFHLEtBQUssS0FBTSxDQUFDLEdBQUcsS0FBSyxLQUFNLENBQUMsR0FBRyxLQUFLLEtBQU0sQ0FBQyxLQUFLLENBQUM7O0FBRzdFLGNBQU0sY0FBYyxRQUFRLFdBQVcsU0FBWSxRQUFRLFNBQVM7QUFHcEUsY0FBTSxlQUNKLFFBQVEsaUJBQWlCLFNBQWEsUUFBUSxpQkFBaUIsU0FBWSxRQUFRLGVBQWUsUUFBUztBQUM3RyxjQUFNLFNBQVMsU0FBUztBQUN4QixjQUFNLGNBQWMsaUJBQWlCLFNBQVMsSUFBSSxhQUFhLFNBQVMsQ0FBQyxJQUFJLElBQUksYUFBYSxTQUFTLENBQUM7QUFHeEcsWUFBSSxPQUFPLEdBQ1QsZ0JBQWdCLEdBQ2hCLGdCQUFnQixHQUNoQixnQkFBZ0IsR0FDaEIsZ0JBQWdCO0FBQ2xCLFlBQUksaUJBQWlCLEdBQ25CLGlCQUFpQixRQUNqQixpQkFBaUIsU0FBUyxHQUMxQixpQkFBaUI7QUFHbkIsWUFBSSxnQkFBZ0IsT0FBTztBQUN6QixpQkFBTztBQUNQLDBCQUFnQjtBQUNoQiwwQkFBZ0I7QUFDaEIsMEJBQWdCO0FBQ2hCLDBCQUFnQjs7QUFJbEIsWUFBSSxpQkFBaUIsUUFBUTtBQUMzQiwyQkFBaUIsU0FBUzttQkFDakIsaUJBQWlCLE9BQU87QUFDakMsMkJBQWlCO0FBQ2pCLDJCQUFpQjtBQUNqQiwyQkFBaUIsU0FBUzttQkFDakIsaUJBQWlCLE9BQU87QUFDakMsMkJBQWlCO0FBQ2pCLDJCQUFpQjtBQUNqQiwyQkFBaUIsU0FBUzs7QUFHNUIsaUJBQ00sSUFBSSxHQUNSLElBQUksUUFDSixLQUFLLGlCQUFpQixNQUFNLGlCQUFpQixNQUFNLGlCQUFpQixNQUFNLGlCQUFpQixNQUMzRjtBQUNBLHNCQUFZLGdCQUFnQixLQUFLLE9BQU8sYUFBYSxJQUFJLFNBQVMsQ0FBQyxLQUFLLFNBQVMsQ0FBQztBQUNsRixzQkFBWSxnQkFBZ0IsS0FBSyxPQUFPLGFBQWEsSUFBSSxTQUFTLENBQUMsS0FBSyxTQUFTLENBQUM7QUFDbEYsc0JBQVksZ0JBQWdCLEtBQUssT0FBTyxhQUFhLElBQUksU0FBUyxDQUFDLEtBQUssU0FBUyxDQUFDO0FBQ2xGLGNBQUksbUJBQW1CLE1BQU0sa0JBQWtCLElBQUk7QUFDakQsd0JBQVksZ0JBQWdCLEtBQUssT0FBTyxhQUFhLElBQUksU0FBUyxDQUFDLEtBQUssU0FBUyxDQUFDOzs7QUFLdEYsY0FBTSxlQUNKLGlCQUFpQixTQUNiLElBQUksT0FBTyxXQUFXLGFBQWEsQ0FBQyxHQUFHLEdBQUcsUUFBUSxLQUFLLENBQUMsSUFDeEQsSUFBSSxPQUFPLFdBQVcsYUFBYSxDQUFDLEdBQUcsR0FBRyxRQUFRLEtBQUssQ0FBQztBQUM5RCxlQUFPO01BQ1Q7QUFLTyxNQUFNLGtCQUFrQixPQUM3QixPQUNBLFlBS21CO0FBRW5CLGNBQU0saUJBQWlCLE9BQU8scUJBQXFCLGVBQWUsaUJBQWlCO0FBQ25GLGNBQU0saUJBQWlCLE9BQU8sY0FBYyxlQUFlLGlCQUFpQjtBQUM1RSxjQUFNLGdCQUFnQixPQUFPLGdCQUFnQixlQUFlLGlCQUFpQjtBQUM3RSxjQUFNLFdBQVcsT0FBTyxVQUFVO0FBRWxDLFlBQUk7QUFDSixZQUFJLHdCQUErQyxXQUFXLENBQUE7QUFFOUQsY0FBTSxlQUFlLE1BQUs7QUFDeEIsY0FBSSxPQUFPLGFBQWEsYUFBYTtBQUNuQyxtQkFBTyxTQUFTLGNBQWMsUUFBUTtxQkFDN0IsT0FBTyxvQkFBb0IsYUFBYTtBQUNqRCxtQkFBTyxJQUFJLGdCQUFnQixHQUFHLENBQUM7aUJBQzFCO0FBQ0wsa0JBQU0sSUFBSSxNQUFNLHlCQUF5Qjs7UUFFN0M7QUFDQSxjQUFNLHNCQUFzQixDQUFDLFdBQStDO0FBQzFFLGNBQUksT0FBTyxzQkFBc0IsZUFBZSxrQkFBa0IsbUJBQW1CO0FBQ25GLG1CQUFPLE9BQU8sV0FBVyxJQUFJO3FCQUNwQixrQkFBa0IsaUJBQWlCO0FBQzVDLG1CQUFPLE9BQU8sV0FBVyxJQUFJO2lCQUN4QjtBQUNMLG1CQUFPOztRQUVYO0FBRUEsWUFBSSxnQkFBZ0I7QUFFbEIsZ0JBQU0sU0FBUyxhQUFZO0FBQzNCLGlCQUFPLFFBQVEsTUFBTTtBQUNyQixpQkFBTyxTQUFTLE1BQU07QUFDdEIsZ0JBQU0sa0JBQWtCLG9CQUFvQixNQUFNO0FBRWxELGNBQUksbUJBQW1CLE1BQU07QUFDM0IsZ0JBQUksU0FBUyxNQUFNO0FBQ25CLGdCQUFJLFFBQVEsTUFBTTtBQUNsQixnQkFBSSxZQUFZLFVBQWEsUUFBUSxrQkFBa0IsVUFBYSxRQUFRLGlCQUFpQixRQUFXO0FBQ3RHLHVCQUFTLFFBQVE7QUFDakIsc0JBQVEsUUFBUTs7QUFHbEIsZ0JBQUksWUFBWSxRQUFXO0FBQ3pCLHNDQUF3QjtBQUN4QixrQkFBSSxRQUFRLGlCQUFpQixRQUFXO0FBQ3RDLHNCQUFNLElBQUksTUFBTSw2REFBNkQ7cUJBQ3hFO0FBQ0wsc0NBQXNCLGVBQWU7O0FBRXZDLG9DQUFzQixTQUFTO0FBQy9CLG9DQUFzQixRQUFRO21CQUN6QjtBQUNMLG9DQUFzQixlQUFlO0FBQ3JDLG9DQUFzQixTQUFTO0FBQy9CLG9DQUFzQixRQUFROztBQUdoQyw0QkFBZ0IsVUFBVSxPQUFPLEdBQUcsQ0FBQztBQUNyQyxtQkFBTyxnQkFBZ0IsYUFBYSxHQUFHLEdBQUcsT0FBTyxNQUFNLEVBQUU7aUJBQ3BEO0FBQ0wsa0JBQU0sSUFBSSxNQUFNLDJCQUEyQjs7bUJBRXBDLGdCQUFnQjtBQUN6QixjQUFJO0FBQ0osY0FBSTtBQUVKLGNBQUksWUFBWSxVQUFhLFFBQVEsaUJBQWlCLFVBQWEsUUFBUSxrQkFBa0IsUUFBVztBQUN0RyxxQkFBUyxRQUFRO0FBQ2pCLG9CQUFRLFFBQVE7aUJBQ1g7QUFDTCxxQkFBUyxNQUFNO0FBQ2Ysb0JBQVEsTUFBTTs7QUFHaEIsY0FBSSxZQUFZLFFBQVc7QUFDekIsb0NBQXdCOztBQUUxQixnQ0FBc0IsU0FBUztBQUMvQixnQ0FBc0IsU0FBUztBQUMvQixnQ0FBc0IsUUFBUTtBQUU5QixjQUFJLFlBQVksUUFBVztBQUN6QixrQkFBTSxhQUFhLGFBQVk7QUFFL0IsdUJBQVcsUUFBUTtBQUNuQix1QkFBVyxTQUFTO0FBRXBCLGtCQUFNLGtCQUFrQixvQkFBb0IsVUFBVTtBQUV0RCxnQkFBSSxtQkFBbUIsTUFBTTtBQUMzQiw4QkFBZ0IsYUFBYSxPQUFPLEdBQUcsQ0FBQztBQUN4QyxxQkFBTyxnQkFBZ0IsYUFBYSxHQUFHLEdBQUcsT0FBTyxNQUFNLEVBQUU7bUJBQ3BEO0FBQ0wsb0JBQU0sSUFBSSxNQUFNLDJCQUEyQjs7aUJBRXhDO0FBQ0wsbUJBQU8sTUFBTTs7bUJBRU4sZUFBZTtBQUV4QixjQUFJLFlBQVksUUFBVztBQUN6QixrQkFBTSxJQUFJLE1BQU0seURBQXlEOztBQUczRSxnQkFBTSxTQUFTLGFBQVk7QUFDM0IsaUJBQU8sUUFBUSxNQUFNO0FBQ3JCLGlCQUFPLFNBQVMsTUFBTTtBQUN0QixnQkFBTSxrQkFBa0Isb0JBQW9CLE1BQU07QUFFbEQsY0FBSSxtQkFBbUIsTUFBTTtBQUMzQixrQkFBTSxTQUFTLE1BQU07QUFDckIsa0JBQU0sUUFBUSxNQUFNO0FBQ3BCLDRCQUFnQixVQUFVLE9BQU8sR0FBRyxHQUFHLE9BQU8sTUFBTTtBQUNwRCxtQkFBTyxnQkFBZ0IsYUFBYSxHQUFHLEdBQUcsT0FBTyxNQUFNLEVBQUU7QUFDekQsa0NBQXNCLFNBQVM7QUFDL0Isa0NBQXNCLFFBQVE7QUFDOUIsbUJBQU8sZUFBZSxNQUFNLHFCQUFxQjtpQkFDNUM7QUFDTCxrQkFBTSxJQUFJLE1BQU0sMkJBQTJCOzttQkFFcEMsVUFBVTtBQUNuQixpQkFBTyxJQUFJLFFBQVEsQ0FBQyxTQUFTLFdBQVU7QUFDckMsa0JBQU0sU0FBUyxhQUFZO0FBQzNCLGtCQUFNLFVBQVUsb0JBQW9CLE1BQU07QUFDMUMsZ0JBQUksQ0FBQyxTQUFTLENBQUMsU0FBUztBQUN0QixxQkFBTyxPQUFNOztBQUVmLGtCQUFNLFdBQVcsSUFBSSxNQUFLO0FBQzFCLHFCQUFTLGNBQWM7QUFDdkIscUJBQVMsTUFBTTtBQUNmLHFCQUFTLFNBQVMsTUFBSztBQUNyQixxQkFBTyxRQUFRLFNBQVM7QUFDeEIscUJBQU8sU0FBUyxTQUFTO0FBQ3pCLHNCQUFRLFVBQVUsVUFBVSxHQUFHLEdBQUcsT0FBTyxPQUFPLE9BQU8sTUFBTTtBQUM3RCxvQkFBTSxNQUFNLFFBQVEsYUFBYSxHQUFHLEdBQUcsT0FBTyxPQUFPLE9BQU8sTUFBTTtBQUVsRSxvQ0FBc0IsU0FBUyxPQUFPO0FBQ3RDLG9DQUFzQixRQUFRLE9BQU87QUFDckMsc0JBQVEsZUFBZSxJQUFJLE1BQU0scUJBQXFCLENBQUM7WUFDekQ7VUFDRixDQUFDO2VBQ0k7QUFDTCxnQkFBTSxJQUFJLE1BQU0sZ0VBQWdFOztBQUdsRixZQUFJLFNBQVMsUUFBVztBQUN0QixpQkFBTyxlQUFlLE1BQU0scUJBQXFCO2VBQzVDO0FBQ0wsZ0JBQU0sSUFBSSxNQUFNLGdFQUFnRTs7TUFFcEY7QUFLTyxNQUFNLG9CQUFvQixDQUMvQixTQUNBLFlBQ1U7QUFDVixjQUFNLEVBQUUsT0FBTyxRQUFRLFVBQVUsUUFBTyxJQUFLO0FBRTdDLGNBQU0sT0FBTyxDQUFDLEdBQUcsUUFBUSxPQUFPLENBQUM7QUFDakMsZUFBTyxJQUFJLE9BQU8sRUFBRSxVQUFVLFdBQVcsTUFBTSxXQUFXLFNBQVMsTUFBTSxVQUFVLFFBQU8sQ0FBRTtNQUM5RjtBQUtPLE1BQU0sc0JBQXNCLENBQ2pDLFdBQ0EsWUFDVTtBQUNWLGNBQU0sRUFBRSxVQUFVLE1BQU0sVUFBVSxRQUFPLElBQUs7QUFDOUMsZUFBTyxJQUFJLE9BQU8sRUFBRSxVQUFVLGNBQWMsTUFBTSxZQUFZLFdBQVcsV0FBVyxNQUFNLFVBQVUsUUFBTyxDQUFFO01BQy9HO0FBS08sTUFBTSxxQkFBcUIsQ0FDaEMsVUFDQSxZQUNVO0FBQ1YsY0FBTSxFQUFFLFVBQVUsTUFBTSxVQUFVLFFBQU8sSUFBSztBQUM5QyxlQUFPLElBQUksT0FBTyxFQUFFLFVBQVUsYUFBYSxNQUFNLFlBQVksV0FBVyxVQUFVLE1BQU0sVUFBVSxRQUFPLENBQUU7TUFDN0c7QUFLTyxNQUFNLHlCQUF5QixDQUNwQyxNQUNBLFFBQ0EsU0FDVyxJQUFJLE9BQU8sRUFBRSxVQUFVLGNBQWMsTUFBTSxNQUFNLFFBQVEsTUFBTSxRQUFRLENBQUMsT0FBTyxNQUFNLEVBQUMsQ0FBRTs7Ozs7QUMzVXJHLE1Bb0JhLHVDQWVBLHVDQWNULHFCQUNTO0FBbERiOzs7QUFvQk8sTUFBTSx3Q0FBd0Msb0JBQUksSUFBNkM7UUFDcEcsQ0FBQyxXQUFXLFlBQVk7UUFDeEIsQ0FBQyxTQUFTLFVBQVU7UUFDcEIsQ0FBQyxRQUFRLFNBQVM7UUFDbEIsQ0FBQyxVQUFVLFdBQVc7UUFDdEIsQ0FBQyxTQUFTLFVBQVU7UUFDcEIsQ0FBQyxTQUFTLFVBQVU7UUFDcEIsQ0FBQyxRQUFRLFVBQVU7UUFDbkIsQ0FBQyxXQUFXLFlBQVk7UUFDeEIsQ0FBQyxVQUFVLFdBQVc7UUFDdEIsQ0FBQyxRQUFRLFVBQVU7UUFDbkIsQ0FBQyxTQUFTLFVBQVU7T0FDckI7QUFHTSxNQUFNLHdDQUF3QyxvQkFBSSxJQUFrRDtRQUN6RyxDQUFDLGNBQWMsU0FBUztRQUN4QixDQUFDLFlBQVksT0FBTztRQUNwQixDQUFDLFdBQVcsTUFBTTtRQUNsQixDQUFDLGFBQWEsUUFBUTtRQUN0QixDQUFDLFlBQVksT0FBTztRQUNwQixDQUFDLFlBQVksT0FBTztRQUNwQixDQUFDLGNBQWMsU0FBUztRQUN4QixDQUFDLGFBQWEsUUFBUTtPQUN2QjtBQUtELE1BQUksc0JBQXNCO0FBQ25CLE1BQU0sa0JBQWtCLE1BQUs7QUFDbEMsWUFBSSxDQUFDLHFCQUFxQjtBQUN4QixnQ0FBc0I7QUFDdEIsZ0JBQU0sMkJBQTJCLE9BQU8sa0JBQWtCLGVBQWUsY0FBYztBQUN2RixnQkFBTSw0QkFBNEIsT0FBTyxtQkFBbUIsZUFBZSxlQUFlO0FBRzFGLGdCQUFNQyxnQkFBZ0IsV0FBbUI7QUFDekMsZ0JBQU0sMEJBQTBCLE9BQU9BLGtCQUFpQixlQUFlQSxjQUFhO0FBRXBGLGNBQUksMEJBQTBCO0FBQzVCLGtEQUFzQyxJQUFJLFNBQVMsYUFBYTtBQUNoRSxrREFBc0MsSUFBSSxlQUFlLE9BQU87O0FBRWxFLGNBQUksMkJBQTJCO0FBQzdCLGtEQUFzQyxJQUFJLFVBQVUsY0FBYztBQUNsRSxrREFBc0MsSUFBSSxnQkFBZ0IsUUFBUTs7QUFFcEUsY0FBSSx5QkFBeUI7QUFDM0Isa0RBQXNDLElBQUksV0FBV0EsYUFBWTtBQUNqRSxrREFBc0MsSUFBSUEsZUFBYyxTQUFTO2lCQUM1RDtBQUVMLGtEQUFzQyxJQUFJLFdBQVcsV0FBVzs7O01BR3RFOzs7OztBQzVFQSxNQWdCYSxlQWtCQTtBQWxDYjs7O0FBU0E7QUFPTyxNQUFNLGdCQUFnQixDQUFDLFNBQW9DO0FBQ2hFLFlBQUksT0FBTztBQUNYLGlCQUFTLElBQUksR0FBRyxJQUFJLEtBQUssUUFBUSxLQUFLO0FBQ3BDLGdCQUFNLE1BQU0sS0FBSyxDQUFDO0FBQ2xCLGNBQUksT0FBTyxRQUFRLFlBQVksQ0FBQyxPQUFPLGNBQWMsR0FBRyxHQUFHO0FBQ3pELGtCQUFNLElBQUksVUFBVSxRQUFRLENBQUMsOEJBQThCLEdBQUcsRUFBRTs7QUFFbEUsY0FBSSxNQUFNLEdBQUc7QUFDWCxrQkFBTSxJQUFJLFdBQVcsUUFBUSxDQUFDLDBDQUEwQyxHQUFHLEVBQUU7O0FBRS9FLGtCQUFROztBQUVWLGVBQU87TUFDVDtBQUtPLE1BQU0sZ0JBQWdCLENBQUMsUUFBZ0IsU0FBbUM7QUFDL0UsZ0JBQVEsT0FBTyxVQUFVO1VBQ3ZCLEtBQUs7QUFDSCxtQkFBTyxJQUFJLE9BQU8sT0FBTyxNQUFNLE9BQU8sTUFBTSxJQUFJO1VBQ2xELEtBQUs7QUFDSCxtQkFBTyxJQUFJLE9BQU87Y0FDaEIsVUFBVTtjQUNWLE1BQU0sT0FBTztjQUNiLE1BQU0sT0FBTztjQUNiO2FBQ0Q7VUFDSCxLQUFLO0FBQ0gsbUJBQU8sSUFBSSxPQUFPO2NBQ2hCLFVBQVU7Y0FDVixTQUFTLE9BQU87Y0FDaEIsTUFBTSxPQUFPO2NBQ2I7YUFDRDtVQUNILEtBQUs7QUFDSCxtQkFBTyxJQUFJLE9BQU87Y0FDaEIsVUFBVTtjQUNWLFdBQVcsT0FBTztjQUNsQixNQUFNLE9BQU87Y0FDYjthQUNEO1VBQ0gsS0FBSztBQUNILG1CQUFPLElBQUksT0FBTztjQUNoQixVQUFVO2NBQ1YsVUFBVSxPQUFPO2NBQ2pCLE1BQU0sT0FBTztjQUNiO2FBQ0Q7VUFDSDtBQUNFLGtCQUFNLElBQUksTUFBTSxrQ0FBa0MsT0FBTyxRQUFRLG1CQUFtQjs7TUFFMUY7Ozs7O0FDckVBLE1BaURhO0FBakRiOzs7QUFHQTtBQUVBO0FBb0JBO0FBT0E7QUFpQk0sTUFBTyxTQUFQLE1BQWE7Ozs7UUF1RGpCLFlBQ0UsTUFVQSxNQUNBLE1BQXdCO0FBR3hCLDBCQUFlO0FBRWYsY0FBSTtBQUNKLGNBQUk7QUFFSixjQUFJLE9BQU8sU0FBUyxZQUFZLGNBQWMsTUFBTTtBQUlsRCxpQkFBSyxlQUFlLEtBQUs7QUFDekIsbUJBQU8sS0FBSztBQUNaLG1CQUFPLEtBQUs7QUFDWixvQkFBUSxLQUFLLFVBQVU7Y0FDckIsS0FBSyxjQUFjO0FBQ2pCLHNCQUFNLGdDQUFnQyxzQ0FBc0MsSUFBSSxJQUFJO0FBQ3BGLG9CQUFJLENBQUMsK0JBQStCO0FBQ2xDLHdCQUFNLElBQUksVUFBVSxxQkFBcUIsSUFBSSx1Q0FBdUM7O0FBRXRGLG9CQUFJLEVBQUUsS0FBSyxnQkFBZ0IsZ0NBQWdDO0FBQ3pELHdCQUFNLElBQUksVUFBVSw0QkFBNEIsOEJBQThCLElBQUksRUFBRTs7QUFFdEYscUJBQUssVUFBVSxLQUFLO0FBQ3BCOztjQUVGLEtBQUssV0FBVztBQUNkLG9CQUFJLFNBQVMsV0FBVztBQUN0Qix3QkFBTSxJQUFJLFVBQVUscUJBQXFCLElBQUksaUNBQWlDOztBQUVoRixxQkFBSyxpQkFBaUIsS0FBSztBQUMzQixxQkFBSyxhQUFhLEtBQUs7QUFDdkIscUJBQUssV0FBVyxLQUFLO0FBQ3JCOztjQUVGLEtBQUssY0FBYztBQUNqQixvQkFDRSxTQUFTLGFBQ1QsU0FBUyxhQUNULFNBQVMsV0FDVCxTQUFTLFdBQ1QsU0FBUyxZQUNULFNBQVMsV0FDVCxTQUFTLFVBQ1QsU0FBUyxXQUNULFNBQVMsUUFDVDtBQUNBLHdCQUFNLElBQUksVUFBVSxxQkFBcUIsSUFBSSxvQ0FBb0M7O0FBRW5GLHFCQUFLLGdCQUFnQixLQUFLO0FBQzFCLHFCQUFLLGFBQWEsS0FBSztBQUN2QixxQkFBSyxXQUFXLEtBQUs7QUFDckI7O2NBRUYsS0FBSyxhQUFhO0FBQ2hCLG9CQUNFLFNBQVMsYUFDVCxTQUFTLGFBQ1QsU0FBUyxXQUNULFNBQVMsV0FDVCxTQUFTLFlBQ1QsU0FBUyxZQUNULFNBQVMsVUFDVCxTQUFTLFdBQ1QsU0FBUyxVQUNULFNBQVMsV0FDVCxTQUFTLFFBQ1Q7QUFDQSx3QkFBTSxJQUFJLFVBQVUscUJBQXFCLElBQUksa0NBQWtDOztBQUVqRixxQkFBSyxlQUFlLEtBQUs7QUFDekIscUJBQUssYUFBYSxLQUFLO0FBQ3ZCLHFCQUFLLFdBQVcsS0FBSztBQUNyQjs7Y0FFRjtBQUNFLHNCQUFNLElBQUksTUFBTSw2Q0FBNkMsS0FBSyxZQUFZLEdBQUc7O2lCQUVoRjtBQUlMLGdCQUFJO0FBQ0osZ0JBQUk7QUFFSixnQkFBSSxPQUFPLFNBQVMsVUFBVTtBQUk1QixxQkFBTztBQUNQLDBCQUFZO0FBQ1osa0JBQUksU0FBUyxVQUFVO0FBRXJCLG9CQUFJLENBQUMsTUFBTSxRQUFRLElBQUksR0FBRztBQUN4Qix3QkFBTSxJQUFJLFVBQVUsZ0RBQWdEOztBQUl0RSx1QkFBTztxQkFDRjtBQUVMLHNCQUFNLHdCQUF3QixzQ0FBc0MsSUFBSSxJQUFJO0FBQzVFLG9CQUFJLDBCQUEwQixRQUFXO0FBQ3ZDLHdCQUFNLElBQUksVUFBVSw0QkFBNEIsSUFBSSxHQUFHOztBQUV6RCxvQkFBSSxNQUFNLFFBQVEsSUFBSSxHQUFHO0FBQ3ZCLHNCQUFLLFNBQVMsYUFBYSwwQkFBMEIsZUFBZ0IsU0FBUyxXQUFXLFNBQVMsUUFBUTtBQVd4RywwQkFBTSxJQUFJLFVBQ1IsY0FBYyxJQUFJLDBEQUEwRCxzQkFBc0IsSUFBSSxXQUFXOzZCQUUxRyxTQUFTLFlBQVksU0FBUyxTQUFTO0FBWWhELDJCQUFRLHNCQUE4QixLQUFLLE1BQU0sTUFBTTt5QkFDbEQ7QUFHTCwyQkFBUSxzQkFBOEIsS0FBSyxJQUFJOzsyQkFFeEMsZ0JBQWdCLHVCQUF1QjtBQUNoRCx5QkFBTzsyQkFDRSxnQkFBZ0IsbUJBQW1CO0FBQzVDLHNCQUFJLFNBQVMsU0FBUztBQUNwQiwyQkFBTyxXQUFXLEtBQUssSUFBSTt5QkFDdEI7QUFDTCwwQkFBTSxJQUFJLFVBQVUseURBQXlEOzsyQkFFdEUsU0FBUyxhQUFhLGdCQUFnQixlQUFlLDBCQUEwQixhQUFhO0FBTXJHLHlCQUFPLElBQUssV0FBbUIsYUFBYSxLQUFLLFFBQVEsS0FBSyxZQUFZLEtBQUssTUFBTTt1QkFDaEY7QUFDTCx3QkFBTSxJQUFJLFVBQVUsS0FBSyxJQUFJLGtDQUFrQyxxQkFBcUIsRUFBRTs7O21CQUdyRjtBQUlMLDBCQUFZO0FBQ1osa0JBQUksTUFBTSxRQUFRLElBQUksR0FBRztBQUV2QixvQkFBSSxLQUFLLFdBQVcsR0FBRztBQUNyQix3QkFBTSxJQUFJLFVBQVUscURBQXFEOztBQUUzRSxzQkFBTSxtQkFBbUIsT0FBTyxLQUFLLENBQUM7QUFDdEMsb0JBQUkscUJBQXFCLFVBQVU7QUFDakMseUJBQU87QUFDUCx5QkFBTzsyQkFDRSxxQkFBcUIsV0FBVztBQUN6Qyx5QkFBTztBQUlQLHlCQUFPLFdBQVcsS0FBSyxJQUFhO3VCQUMvQjtBQUNMLHdCQUFNLElBQUksVUFBVSx1Q0FBdUMsZ0JBQWdCLEdBQUc7O3lCQUV2RSxnQkFBZ0IsbUJBQW1CO0FBQzVDLHVCQUFPO0FBQ1AsdUJBQU8sV0FBVyxLQUFLLElBQUk7cUJBQ3RCO0FBRUwsc0JBQU0sYUFBYSxzQ0FBc0MsSUFDdkQsS0FBSyxXQUE4QztBQUVyRCxvQkFBSSxlQUFlLFFBQVc7QUFDNUIsd0JBQU0sSUFBSSxVQUFVLHFDQUFxQyxLQUFLLFdBQVcsR0FBRzs7QUFFOUUsdUJBQU87QUFDUCx1QkFBTzs7O0FBS1gsZ0JBQUksY0FBYyxRQUFXO0FBRTNCLDBCQUFZLENBQUMsS0FBSyxNQUFNO3VCQUNmLENBQUMsTUFBTSxRQUFRLFNBQVMsR0FBRztBQUNwQyxvQkFBTSxJQUFJLFVBQVUsd0NBQXdDOztBQUU5RCxtQkFBTztBQUVQLGlCQUFLLFVBQVU7QUFDZixpQkFBSyxlQUFlOztBQUl0QixnQkFBTSxPQUFPLGNBQWMsSUFBSTtBQUUvQixjQUFJLEtBQUssV0FBVyxTQUFTLEtBQUssUUFBUSxRQUFRO0FBQ2hELGlCQUFLLFNBQVMsV0FBVyxTQUFTLFdBQVcsS0FBSyxLQUFLLE9BQU8sQ0FBQyxNQUFNLEtBQUssUUFBUSxRQUFRO21CQUVuRjtBQUNMLG9CQUFNLElBQUksTUFBTSxpQkFBaUIsSUFBSSxnQ0FBZ0MsS0FBSyxRQUFRLE1BQU0sSUFBSTs7O0FBSWhHLGVBQUssT0FBTztBQUNaLGVBQUssT0FBTztBQUNaLGVBQUssT0FBTztRQUNkOzs7UUFJQSxhQUFhLFVBQ1gsT0FDQSxTQUl3QjtBQUV4QixpQkFBTyxnQkFBZ0IsT0FBTyxPQUFPO1FBQ3ZDO1FBRUEsT0FBTyxZQUNMLFNBQ0EsU0FBb0M7QUFFcEMsaUJBQU8sa0JBQWtCLFNBQVMsT0FBTztRQUMzQztRQUVBLE9BQU8sY0FDTCxXQUNBLFNBQXNDO0FBRXRDLGlCQUFPLG9CQUFvQixXQUFXLE9BQU87UUFDL0M7UUFFQSxPQUFPLGFBQ0wsVUFDQSxTQUFxQztBQUVyQyxpQkFBTyxtQkFBbUIsVUFBVSxPQUFPO1FBQzdDO1FBRUEsT0FBTyxpQkFDTCxNQUNBLFFBQ0EsTUFBd0I7QUFFeEIsaUJBQU8sdUJBQXVCLE1BQU0sUUFBUSxJQUFJO1FBQ2xEOzs7UUFLQSxVQUFVLFNBQWdDO0FBQ3hDLGlCQUFPLGdCQUFnQixNQUFNLE9BQU87UUFDdEM7UUFFQSxZQUFZLFNBQWtDO0FBQzVDLGlCQUFPLGtCQUFrQixNQUFNLE9BQU87UUFDeEM7OztRQXFEQSxJQUFJLE9BQUk7QUFDTixlQUFLLFlBQVc7QUFDaEIsY0FBSSxDQUFDLEtBQUssU0FBUztBQUNqQixrQkFBTSxJQUFJLE1BQ1IsZ0pBQzZFOztBQUdqRixpQkFBTyxLQUFLO1FBQ2Q7UUFFQSxJQUFJLFdBQVE7QUFDVixpQkFBTyxLQUFLO1FBQ2Q7UUFFQSxJQUFJLFVBQU87QUFDVCxlQUFLLFlBQVc7QUFDaEIsY0FBSSxDQUFDLEtBQUssZ0JBQWdCO0FBQ3hCLGtCQUFNLElBQUksTUFBTSw0Q0FBNEM7O0FBRTlELGlCQUFPLEtBQUs7UUFDZDtRQUVBLElBQUksWUFBUztBQUNYLGVBQUssWUFBVztBQUNoQixjQUFJLENBQUMsS0FBSyxlQUFlO0FBQ3ZCLGtCQUFNLElBQUksTUFBTSw0Q0FBNEM7O0FBRTlELGlCQUFPLEtBQUs7UUFDZDtRQUVBLElBQUksV0FBUTtBQUNWLGVBQUssWUFBVztBQUNoQixjQUFJLENBQUMsS0FBSyxjQUFjO0FBQ3RCLGtCQUFNLElBQUksTUFBTSw2Q0FBNkM7O0FBRS9ELGlCQUFPLEtBQUs7UUFDZDs7O1FBS0EsTUFBTSxRQUFRLGFBQXFCO0FBQ2pDLGVBQUssWUFBVztBQUNoQixrQkFBUSxLQUFLLGNBQWM7WUFDekIsS0FBSztZQUNMLEtBQUs7QUFDSCxxQkFBTyxLQUFLO1lBQ2QsS0FBSztZQUNMLEtBQUs7WUFDTCxLQUFLLGFBQWE7QUFDaEIsa0JBQUksQ0FBQyxLQUFLLFlBQVk7QUFDcEIsc0JBQU0sSUFBSSxNQUFNLHFFQUFxRTs7QUFFdkYsa0JBQUksS0FBSyxlQUFlO0FBQ3RCLHNCQUFNLElBQUksTUFBTSx5Q0FBeUM7O0FBRTNELGtCQUFJO0FBQ0YscUJBQUssZ0JBQWdCO0FBQ3JCLHNCQUFNLE9BQU8sTUFBTSxLQUFLLFdBQVU7QUFDbEMscUJBQUssYUFBYTtBQUNsQixxQkFBSyxlQUFlO0FBQ3BCLHFCQUFLLFVBQVU7QUFFZixvQkFBSSxlQUFlLEtBQUssVUFBVTtBQUNoQyx1QkFBSyxTQUFRO0FBQ2IsdUJBQUssV0FBVzs7QUFHbEIsdUJBQU87O0FBRVAscUJBQUssZ0JBQWdCOzs7WUFHekI7QUFDRSxvQkFBTSxJQUFJLE1BQU0sa0NBQWtDLEtBQUssWUFBWSxFQUFFOztRQUUzRTtRQUVBLFVBQU87QUFDTCxjQUFJLEtBQUssZUFBZTtBQUN0QixrQkFBTSxJQUFJLE1BQU0seUNBQXlDOztBQUczRCxjQUFJLEtBQUssVUFBVTtBQUNqQixpQkFBSyxTQUFRO0FBQ2IsaUJBQUssV0FBVzs7QUFFbEIsZUFBSyxVQUFVO0FBQ2YsZUFBSyxpQkFBaUI7QUFDdEIsZUFBSyxnQkFBZ0I7QUFDckIsZUFBSyxlQUFlO0FBQ3BCLGVBQUssYUFBYTtBQUNsQixlQUFLLGdCQUFnQjtBQUVyQixlQUFLLGVBQWU7UUFDdEI7OztRQUtRLGNBQVc7QUFDakIsY0FBSSxLQUFLLGlCQUFpQixRQUFRO0FBQ2hDLGtCQUFNLElBQUksTUFBTSx5QkFBeUI7O1FBRTdDO1FBRUEsUUFBUSxNQUF1QjtBQUM3QixlQUFLLFlBQVc7QUFDaEIsY0FBSSxLQUFLLGNBQWMsS0FBSyxVQUFVO0FBQ3BDLGtCQUFNLElBQUksTUFBTSxpREFBaUQ7O0FBRW5FLGlCQUFPLGNBQWMsTUFBTSxJQUFJO1FBQ2pDOzs7Ozs7QUMvaUJGLE1Bc1lhQztBQXRZYjs7O0FBSUE7QUFrWU8sTUFBTUEsVUFBUzs7Ozs7QUN0WXRCLE1BUWEsT0FRUCxZQXFCTyxrQkFVQTtBQS9DYjs7O0FBR0E7QUFLTyxNQUFNLFFBQVEsQ0FBQyxZQUFvQixVQUFpQjtBQUN6RCxZQUFJLE9BQU8sSUFBSSxVQUFVLGNBQWMsQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUFDLElBQUksT0FBTztBQUNuRTs7QUFHRixnQkFBUSxVQUFVLEdBQUcsVUFBVSxVQUFVLEtBQUssRUFBRTtNQUNsRDtBQUVBLE1BQU0sYUFBYSxDQUFDLEtBQWEsYUFBcUI7QUFDcEQsY0FBTSxRQUFRLElBQUksTUFBSyxFQUFHLE9BQU8sTUFBTSxhQUFhLEtBQUssQ0FBQTtBQUN6RCxZQUFJLGVBQWU7QUFDbkIsaUJBQVMsSUFBSSxHQUFHLElBQUksTUFBTSxRQUFRLEtBQUs7QUFDckMsY0FBSSxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsRUFBRSxTQUFTLFlBQVksR0FBRztBQUNwRCxnQkFBSSxRQUFRLFFBQVEsR0FBRyxLQUFLLE1BQU0sQ0FBQyxFQUFFLEtBQUksRUFBRyxNQUFNLEdBQUcsRUFBRSxDQUFDLENBQUM7QUFDekQsZ0JBQUksVUFBVTtBQUNaLHVCQUFTLEtBQUssUUFBUTs7QUFFeEIsa0JBQU0sT0FBTyxLQUFLO0FBQ2xCOztBQUVGLGNBQUksTUFBTSxDQUFDLEVBQUUsU0FBUyxZQUFZLEdBQUc7QUFDbkMsMkJBQWU7OztNQUdyQjtBQUtPLE1BQU0sbUJBQW1CLENBQUMsYUFBcUI7QUFDcEQsWUFBSSxPQUFPLElBQUksVUFBVSxjQUFjLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQyxJQUFJLE9BQU87QUFDbkU7O0FBRUYsbUJBQVcsU0FBUyxRQUFRO01BQzlCO0FBS08sTUFBTSxpQkFBaUIsQ0FBQyxhQUFxQjtBQUNsRCxZQUFJLE9BQU8sSUFBSSxVQUFVLGNBQWMsQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUFDLElBQUksT0FBTztBQUNuRTs7QUFFRixtQkFBVyxPQUFPLFFBQVE7TUFDNUI7Ozs7O0FDcERBLE1BZ0JhO0FBaEJiOzs7QUFHQTtBQUlBO0FBQ0E7QUFRTSxNQUFPLG1CQUFQLE1BQU8sa0JBQWdCO1FBQzNCLFlBQW9CLFNBQWdDO0FBQ2xELGVBQUssVUFBVTtRQUNqQjtRQUdBLE1BQU0sSUFBSSxPQUFrQixNQUFpQyxNQUFpQjtBQUM1RSwyQkFBZ0I7QUFDaEIsZ0JBQU0sVUFBZ0QsQ0FBQTtBQUN0RCxjQUFJLFVBQXNCLENBQUE7QUFFMUIsY0FBSSxPQUFPLFVBQVUsWUFBWSxVQUFVLFFBQVEsaUJBQWlCQyxXQUFVLE1BQU0sUUFBUSxLQUFLLEdBQUc7QUFDbEcsa0JBQU0sSUFBSSxVQUNSLCtGQUErRjs7QUFJbkcsY0FBSSxpQkFBaUI7QUFFckIsY0FBSSxPQUFPLFNBQVMsVUFBVTtBQUM1QixnQkFBSSxTQUFTLE1BQU07QUFDakIsb0JBQU0sSUFBSSxVQUFVLHlDQUF5Qzs7QUFFL0QsZ0JBQUksZ0JBQWdCQSxTQUFRO0FBQzFCLG9CQUFNLElBQUksVUFBVSw4QkFBOEI7O0FBR3BELGdCQUFJLE1BQU0sUUFBUSxJQUFJLEdBQUc7QUFDdkIsa0JBQUksS0FBSyxXQUFXLEdBQUc7QUFDckIsc0JBQU0sSUFBSSxVQUFVLHFDQUFxQzs7QUFFM0QsK0JBQWlCO0FBRWpCLHlCQUFXLFFBQVEsTUFBTTtBQUN2QixvQkFBSSxPQUFPLFNBQVMsVUFBVTtBQUM1Qix3QkFBTSxJQUFJLFVBQVUsZ0RBQWdEOztBQUV0RSxvQkFBSSxLQUFLLFlBQVksUUFBUSxJQUFJLE1BQU0sSUFBSTtBQUN6Qyx3QkFBTSxJQUFJLFdBQVcsMkNBQTJDLElBQUksR0FBRzs7QUFFekUsd0JBQVEsSUFBSSxJQUFJOztBQUdsQixrQkFBSSxPQUFPLFNBQVMsWUFBWSxTQUFTLE1BQU07QUFDN0MsMEJBQVU7eUJBQ0QsT0FBTyxTQUFTLGFBQWE7QUFDdEMsc0JBQU0sSUFBSSxVQUFVLDhCQUE4Qjs7bUJBRS9DO0FBR0wsa0JBQUksWUFBWTtBQUNoQixvQkFBTSxXQUFXLE9BQU8sb0JBQW9CLElBQUk7QUFDaEQseUJBQVcsUUFBUSxLQUFLLGFBQWE7QUFDbkMsb0JBQUksU0FBUyxRQUFRLElBQUksTUFBTSxJQUFJO0FBQ2pDLHdCQUFNLElBQUssS0FBNEQsSUFBSTtBQUMzRSxzQkFBSSxNQUFNLFFBQVEsYUFBYUEsU0FBUTtBQUNyQyxnQ0FBWTtBQUNaLHFDQUFpQjtBQUNqQiw0QkFBUSxJQUFJLElBQUk7Ozs7QUFLdEIsa0JBQUksV0FBVztBQUNiLG9CQUFJLE9BQU8sU0FBUyxZQUFZLFNBQVMsTUFBTTtBQUM3Qyw0QkFBVTsyQkFDRCxPQUFPLFNBQVMsYUFBYTtBQUN0Qyx3QkFBTSxJQUFJLFVBQVUsOEJBQThCOztxQkFFL0M7QUFDTCwwQkFBVTs7O3FCQUdMLE9BQU8sU0FBUyxhQUFhO0FBQ3RDLGtCQUFNLElBQUksVUFBVSx5REFBeUQ7O0FBSS9FLHFCQUFXLFFBQVEsS0FBSyxZQUFZO0FBQ2xDLGdCQUFJLE9BQU8sTUFBTSxJQUFJLE1BQU0sYUFBYTtBQUN0QyxvQkFBTSxJQUFJLE1BQU0sVUFBVSxJQUFJLDBCQUEwQjs7O0FBSzVELGNBQUksZ0JBQWdCO0FBQ2xCLHVCQUFXLFFBQVEsS0FBSyxhQUFhO0FBQ25DLHNCQUFRLElBQUksSUFBSTs7O0FBTXBCLGdCQUFNLFVBQVUsTUFBTSxLQUFLLFFBQVEsSUFBSSxPQUFPLFNBQVMsT0FBTztBQUM5RCxnQkFBTSxjQUE2QyxDQUFBO0FBQ25ELHFCQUFXLE9BQU8sU0FBUztBQUN6QixnQkFBSSxPQUFPLGVBQWUsS0FBSyxTQUFTLEdBQUcsR0FBRztBQUM1QyxvQkFBTSxTQUFTLFFBQVEsR0FBRztBQUMxQixrQkFBSSxrQkFBa0JBLFNBQVE7QUFDNUIsNEJBQVksR0FBRyxJQUFJO3FCQUNkO0FBQ0wsNEJBQVksR0FBRyxJQUFJLElBQUlBLFFBQU8sT0FBTyxNQUFNLE9BQU8sTUFBTSxPQUFPLElBQUk7Ozs7QUFJekUseUJBQWM7QUFDZCxpQkFBTztRQUNUO1FBRUEsTUFBTSxVQUFPO0FBQ1gsaUJBQU8sS0FBSyxRQUFRLFFBQU87UUFDN0I7UUFXQSxhQUFhLE9BQ1gsTUFDQSxNQUNBLE1BQ0EsTUFBcUI7QUFFckIsMkJBQWdCO0FBRWhCLGNBQUk7QUFDSixjQUFJLFVBQTBCLENBQUE7QUFFOUIsY0FBSSxPQUFPLFNBQVMsVUFBVTtBQUM1QixtQ0FBdUI7QUFDdkIsZ0JBQUksT0FBTyxTQUFTLFlBQVksU0FBUyxNQUFNO0FBQzdDLHdCQUFVO3VCQUNELE9BQU8sU0FBUyxhQUFhO0FBQ3RDLG9CQUFNLElBQUksVUFBVSw4QkFBOEI7O3FCQUUzQyxnQkFBZ0IsWUFBWTtBQUNyQyxtQ0FBdUI7QUFDdkIsZ0JBQUksT0FBTyxTQUFTLFlBQVksU0FBUyxNQUFNO0FBQzdDLHdCQUFVO3VCQUNELE9BQU8sU0FBUyxhQUFhO0FBQ3RDLG9CQUFNLElBQUksVUFBVSw4QkFBOEI7O3FCQUdwRCxnQkFBZ0IsZUFDZixPQUFPLHNCQUFzQixlQUFlLGdCQUFnQixtQkFDN0Q7QUFDQSxrQkFBTSxTQUFTO0FBQ2YsZ0JBQUksYUFBYTtBQUNqQixnQkFBSSxhQUFhLEtBQUs7QUFDdEIsZ0JBQUksT0FBTyxTQUFTLFlBQVksU0FBUyxNQUFNO0FBQzdDLHdCQUFVO3VCQUNELE9BQU8sU0FBUyxVQUFVO0FBQ25DLDJCQUFhO0FBQ2Isa0JBQUksQ0FBQyxPQUFPLGNBQWMsVUFBVSxHQUFHO0FBQ3JDLHNCQUFNLElBQUksV0FBVyxrQ0FBa0M7O0FBRXpELGtCQUFJLGFBQWEsS0FBSyxjQUFjLE9BQU8sWUFBWTtBQUNyRCxzQkFBTSxJQUFJLFdBQVcsb0NBQW9DLE9BQU8sVUFBVSxJQUFJOztBQUVoRiwyQkFBYSxLQUFLLGFBQWE7QUFDL0Isa0JBQUksT0FBTyxTQUFTLFVBQVU7QUFDNUIsNkJBQWE7QUFDYixvQkFBSSxDQUFDLE9BQU8sY0FBYyxVQUFVLEdBQUc7QUFDckMsd0JBQU0sSUFBSSxXQUFXLGtDQUFrQzs7QUFFekQsb0JBQUksY0FBYyxLQUFLLGFBQWEsYUFBYSxPQUFPLFlBQVk7QUFDbEUsd0JBQU0sSUFBSSxXQUFXLG9DQUFvQyxPQUFPLGFBQWEsVUFBVSxJQUFJOztBQUU3RixvQkFBSSxPQUFPLFNBQVMsWUFBWSxTQUFTLE1BQU07QUFDN0MsNEJBQVU7MkJBQ0QsT0FBTyxTQUFTLGFBQWE7QUFDdEMsd0JBQU0sSUFBSSxVQUFVLDhCQUE4Qjs7eUJBRTNDLE9BQU8sU0FBUyxhQUFhO0FBQ3RDLHNCQUFNLElBQUksVUFBVSxnQ0FBZ0M7O3VCQUU3QyxPQUFPLFNBQVMsYUFBYTtBQUN0QyxvQkFBTSxJQUFJLFVBQVUsOEJBQThCOztBQUVwRCxtQ0FBdUIsSUFBSSxXQUFXLFFBQVEsWUFBWSxVQUFVO2lCQUMvRDtBQUNMLGtCQUFNLElBQUksVUFBVSxxREFBcUQ7O0FBSTNFLGdCQUFNLENBQUMsU0FBUyx1QkFBdUIsSUFBSSxNQUFNLG9DQUFvQyxPQUFPO0FBQzVGLGdCQUFNLFVBQVUsTUFBTSxRQUFRLDhCQUE4QixzQkFBc0IsdUJBQXVCO0FBQ3pHLHlCQUFjO0FBQ2QsaUJBQU8sSUFBSSxrQkFBaUIsT0FBTztRQUNyQztRQUVBLGlCQUFjO0FBQ1osZUFBSyxRQUFRLGVBQWM7UUFDN0I7UUFDQSxlQUFZO0FBQ1YsZUFBSyxRQUFRLGFBQVk7UUFDM0I7UUFFQSxJQUFJLGFBQVU7QUFDWixpQkFBTyxLQUFLLFFBQVE7UUFDdEI7UUFDQSxJQUFJLGNBQVc7QUFDYixpQkFBTyxLQUFLLFFBQVE7UUFDdEI7UUFFQSxJQUFJLGdCQUFhO0FBQ2YsaUJBQU8sS0FBSyxRQUFRO1FBQ3RCO1FBRUEsSUFBSSxpQkFBYztBQUNoQixpQkFBTyxLQUFLLFFBQVE7UUFDdEI7Ozs7OztBQ3pPRixNQTJtQmFDO0FBM21CYjs7O0FBR0E7QUF3bUJPLE1BQU1BLG9CQUE0Qzs7Ozs7QUMzbUJ6RDs7Ozs7OztBQ0FBOzs7Ozs7O0FDQUE7Ozs7Ozs7QUNBQTs7Ozs7OztBQ0FBOzs0QkFBQUM7SUFBQTs7O2tCQUFBQztJQUFBLFdBQUFDO0lBQUE7Ozs7O0FBbUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUMzQkEsTUFHYTtBQUhiO0FBQUE7QUFBQTtBQUdPLE1BQU0sU0FBUztBQUFBO0FBQUE7OztBQ0h0QjtBQUFBO0FBQUE7QUFBQTtBQUFBLE1BbUdNLGFBQ0EsZUEwRkM7QUE5TFA7QUFBQTtBQUFBO0FBc0ZBO0FBVUE7QUFDQTtBQUVBLE1BQU0sY0FBYztBQUNwQixNQUFNLGdCQUFnQixXQUFXLE1BQU0sU0FBUztBQUVoRCxVQUFJLGVBQWU7QUFFakIsYUFBSyxZQUFZLENBQUMsT0FBMkM7QUFDM0QsZ0JBQU0sRUFBRSxNQUFNLElBQUksUUFBUSxJQUFJLEdBQUc7QUFDakMsY0FBSTtBQUNGLG9CQUFRLE1BQU07QUFBQSxjQUNaLEtBQUs7QUFDSCxzQ0FBc0IsUUFBUyxJQUFJLEVBQUU7QUFBQSxrQkFDbkMsTUFBTTtBQUNKLGdDQUFZLE9BQVEsRUFBRTtBQUFBLHNCQUNwQixNQUFNO0FBQ0osb0NBQVksRUFBRSxLQUFLLENBQUM7QUFBQSxzQkFDdEI7QUFBQSxzQkFDQSxDQUFDLFFBQVE7QUFDUCxvQ0FBWSxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQUEsc0JBQzNCO0FBQUEsb0JBQ0Y7QUFBQSxrQkFDRjtBQUFBLGtCQUNBLENBQUMsUUFBUTtBQUNQLGdDQUFZLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFBQSxrQkFDM0I7QUFBQSxnQkFDRjtBQUNBO0FBQUEsY0FDRixLQUFLLFdBQVc7QUFDZCxzQkFBTSxFQUFFLFFBQVEsS0FBQUMsS0FBSSxJQUFJO0FBQ3hCLHVCQUFPQSxNQUFLLE1BQU0sRUFBRTtBQUFBLGtCQUNsQixNQUFNO0FBQ0osZ0NBQVksRUFBRSxLQUFLLENBQUM7QUFBQSxrQkFDdEI7QUFBQSxrQkFDQSxDQUFDLFFBQVE7QUFDUCxnQ0FBWSxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQUEsa0JBQzNCO0FBQUEsZ0JBQ0Y7QUFDQTtBQUFBLGNBQ0Y7QUFBQSxjQUNBLEtBQUssYUFBYTtBQUNoQixzQkFBTSxFQUFFLE9BQU8sSUFBSTtBQUNuQixzQkFBTSxhQUFhLHVCQUF1QixNQUFNO0FBQ2hELDRCQUFZLEVBQUUsTUFBTSxLQUFLLFdBQVcsQ0FBbUI7QUFDdkQ7QUFBQSxjQUNGO0FBQUEsY0FDQSxLQUFLLFVBQVU7QUFDYixzQkFBTSxFQUFFLE9BQU8sUUFBUSxJQUFJO0FBQzNCLDhCQUFjLE9BQU8sT0FBTyxFQUFFO0FBQUEsa0JBQzVCLENBQUMsb0JBQW9CO0FBQ25CLGdDQUFZLEVBQUUsTUFBTSxLQUFLLGdCQUFnQixDQUFtQjtBQUFBLGtCQUM5RDtBQUFBLGtCQUNBLENBQUMsUUFBUTtBQUNQLGdDQUFZLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFBQSxrQkFDM0I7QUFBQSxnQkFDRjtBQUNBO0FBQUEsY0FDRjtBQUFBLGNBQ0EsS0FBSztBQUNILCtCQUFlLE9BQVE7QUFDdkIsNEJBQVksRUFBRSxLQUFLLENBQUM7QUFDcEI7QUFBQSxjQUNGLEtBQUssT0FBTztBQUNWLHNCQUFNLEVBQUUsV0FBVyxjQUFjLFFBQVEsZUFBZSxRQUFRLElBQUk7QUFDcEUsb0JBQUksV0FBVyxjQUFjLFFBQVEsZUFBZSxJQUFJLE1BQU0sY0FBYyxNQUFNLEVBQUUsS0FBSyxJQUFJLEdBQUcsT0FBTyxFQUFFO0FBQUEsa0JBQ3ZHLENBQUMsWUFBWTtBQUNYLHdCQUFJLFFBQVEsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLE1BQU0sS0FBSyxHQUFHO0FBQ3ZDLGtDQUFZLEVBQUUsTUFBTSxLQUFLLGtEQUFrRCxDQUFDO0FBQUEsb0JBQzlFLE9BQU87QUFDTDtBQUFBLHdCQUNFLEVBQUUsTUFBTSxLQUFLLFFBQVE7QUFBQSx3QkFDckIsMkJBQTJCLENBQUMsR0FBRyxRQUFRLEdBQUcsT0FBTyxDQUFpQztBQUFBLHNCQUNwRjtBQUFBLG9CQUNGO0FBQUEsa0JBQ0Y7QUFBQSxrQkFDQSxDQUFDLFFBQVE7QUFDUCxnQ0FBWSxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQUEsa0JBQzNCO0FBQUEsZ0JBQ0Y7QUFDQTtBQUFBLGNBQ0Y7QUFBQSxjQUNBLEtBQUs7QUFDSCw2QkFBYSxPQUFRO0FBQ3JCLDRCQUFZLEVBQUUsS0FBSyxDQUFDO0FBQ3BCO0FBQUEsY0FDRjtBQUFBLFlBQ0Y7QUFBQSxVQUNGLFNBQVMsS0FBSztBQUNaLHdCQUFZLEVBQUUsTUFBTSxJQUFJLENBQW1CO0FBQUEsVUFDN0M7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVBLE1BQU8sZUFBUSxnQkFDWCxPQUNBLENBQUMsZ0JBQ0MsSUFBSSxPQUFPLGVBQWUsV0FBWSxFQUFFLE1BQU0sUUFBb0IsV0FBVyxXQUFXLE1BQU0sWUFBWSxDQUFDO0FBQUE7QUFBQTs7O0FDak1qSCxNQVdNLFFBbUNBLGNBaURPLFdBT0Esa0NBVVAsY0FhQSxjQWFBLGFBY0EsU0FlQSxzQkFRQSxtQkFlTyxtQkFvQlAsb0JBc0JPO0FBeE9iO0FBQUE7QUFBQTtBQUlBO0FBT0EsTUFBTSxTQUFTLFVBQVUsT0FBTyxhQUFhLGNBQWMsU0FBWSxTQUFTO0FBbUNoRixNQUFNLGVBQWUsTUFBMEI7QUFFN0MsWUFBSSxRQUFRO0FBQ1YsaUJBQU87QUFBQSxRQUNUO0FBRUEsWUFBSSxPQUFtQjtBQVNyQixjQUFJLHNDQUFzQztBQWN4QyxrQkFBTSxPQUFPO0FBQ2IsbUJBQU8sSUFBSSxJQUFJLElBQUksS0FBSyxpQkFBNEIsTUFBOEIsRUFBRSxNQUFNLE1BQU0sRUFBRTtBQUFBLFVBQ3BHO0FBRUEsaUJBQU87QUFBQSxRQUNUO0FBRUEsZUFBTyxPQUFPLGFBQWEsY0FDdEIsU0FBUyxlQUFxQztBQUFBO0FBQUEsVUFFL0MsT0FBTyxTQUFTLGNBQ2QsS0FBSyxVQUFVLE9BQ2Y7QUFBQTtBQUFBLE1BQ1I7QUFPTyxNQUFNLFlBQVksYUFBYTtBQU8vQixNQUFNLG1DQUFtQyxNQUEwQjtBQUN4RSxZQUFJLGFBQWEsQ0FBQyxVQUFVLFdBQVcsT0FBTyxHQUFHO0FBQy9DLGlCQUFPLFVBQVUsVUFBVSxHQUFHLFVBQVUsWUFBWSxHQUFHLElBQUksQ0FBQztBQUFBLFFBQzlEO0FBQ0EsZUFBTztBQUFBLE1BQ1Q7QUFLQSxNQUFNLGVBQWUsQ0FBQyxVQUFrQixtQkFBNEI7QUFDbEUsWUFBSTtBQUNGLGdCQUFNLFVBQVUsa0JBQWtCO0FBQ2xDLGdCQUFNLE1BQU0sVUFBVSxJQUFJLElBQUksVUFBVSxPQUFPLElBQUksSUFBSSxJQUFJLFFBQVE7QUFDbkUsaUJBQU8sSUFBSSxXQUFXO0FBQUEsUUFDeEIsUUFBUTtBQUNOLGlCQUFPO0FBQUEsUUFDVDtBQUFBLE1BQ0Y7QUFLQSxNQUFNLGVBQWUsQ0FBQyxVQUFrQixtQkFBNEI7QUFDbEUsY0FBTSxVQUFVLGtCQUFrQjtBQUNsQyxZQUFJO0FBQ0YsZ0JBQU0sTUFBTSxVQUFVLElBQUksSUFBSSxVQUFVLE9BQU8sSUFBSSxJQUFJLElBQUksUUFBUTtBQUNuRSxpQkFBTyxJQUFJO0FBQUEsUUFDYixRQUFRO0FBQ04saUJBQU87QUFBQSxRQUNUO0FBQUEsTUFDRjtBQUtBLE1BQU0sY0FBYyxDQUFDLFVBQWtCLG1CQUE0QixHQUFHLGtCQUFrQixJQUFJLEdBQUcsUUFBUTtBQWN2RyxNQUFNLFVBQVUsT0FBTyxnQkFBeUM7QUFDOUQsY0FBTSxXQUFXLE1BQU0sTUFBTSxhQUFhLEVBQUUsYUFBYSxjQUFjLENBQUM7QUFDeEUsY0FBTSxPQUFPLE1BQU0sU0FBUyxLQUFLO0FBQ2pDLGVBQU8sSUFBSSxnQkFBZ0IsSUFBSTtBQUFBLE1BQ2pDO0FBV0EsTUFBTSx1QkFBdUIsT0FBVSxTQUNwQyxNQUFNO0FBQUE7QUFBQSxRQUFpQztBQUFBLFNBQU07QUFPaEQsTUFBTTtBQUFBLE1BRUosUUFBZ0MsU0FBWSwwQ0FBK0I7QUFhdEUsTUFBTSxvQkFBb0IsWUFBbUQ7QUFDbEYsWUFBSSxDQUFDLFdBQVc7QUFDZCxnQkFBTSxJQUFJLE1BQU0sc0VBQXNFO0FBQUEsUUFDeEY7QUFHQSxZQUFJLGFBQWEsU0FBUyxHQUFHO0FBQzNCLGlCQUFPLENBQUMsUUFBVyxrQkFBbUIsQ0FBQztBQUFBLFFBQ3pDO0FBR0EsY0FBTSxNQUFNLE1BQU0sUUFBUSxTQUFTO0FBQ25DLGVBQU8sQ0FBQyxLQUFLLGtCQUFtQixHQUFHLENBQUM7QUFBQSxNQUN0QztBQU9BLE1BQU0scUJBQ0o7QUFBQTtBQUFBLFNBR00sT0FERixhQUlFO0FBQUEsVUFDRjtBQWNDLE1BQU0sbUJBQW1CLE9BQzlCLGFBQ0EsZ0JBQ0Esb0JBQzBFO0FBQzFFLFlBQUksQ0FBQyxlQUFlLENBQUMsa0JBQWtCLHNCQUFzQixhQUFhLGFBQWEsU0FBUyxHQUFHO0FBQ2pHLGlCQUFPLENBQUMsUUFBVyxrQkFBa0I7QUFBQSxRQUN2QyxPQUFPO0FBQ0wsZ0JBQU0scUJBQXFCLE9BQ3ZCLG9DQUNBO0FBQ0osZ0JBQU0sZ0JBQWdCLGVBQWUsYUFBYSxvQkFBb0IsY0FBYztBQVdwRixnQkFBTSxjQUFjLENBQUMsVUFBVSxtQkFBbUIsaUJBQWlCLENBQUMsYUFBYSxlQUFlLGNBQWM7QUFDOUcsZ0JBQU0sTUFBTSxjQUNSLE1BQU0sUUFBUSxhQUFhLElBQzFCLGlCQUFpQixZQUFZLG9CQUFvQixjQUFjO0FBQ3BFLGlCQUFPLENBQUMsY0FBYyxNQUFNLFFBQVcsTUFBTSxxQkFBNkQsR0FBRyxDQUFDO0FBQUEsUUFDaEg7QUFBQSxNQUNGO0FBQUE7QUFBQTs7O0FDcFFBLE1BUUksTUFDQSxhQUNBLGNBQ0EsU0FFRSx3QkEwQkEsaUJBMkJBLHdCQTRCTyx1QkF1SUE7QUFyT2I7QUFBQTtBQUFBO0FBTUE7QUFHQSxNQUFJLGNBQWM7QUFDbEIsTUFBSSxlQUFlO0FBQ25CLE1BQUksVUFBVTtBQUVkLE1BQU0seUJBQXlCLE1BQWU7QUFFNUMsWUFBSSxPQUFPLHNCQUFzQixhQUFhO0FBQzVDLGlCQUFPO0FBQUEsUUFDVDtBQUVBLFlBQUk7QUFHRixjQUFJLE9BQU8sbUJBQW1CLGFBQWE7QUFDekMsZ0JBQUksZUFBZSxFQUFFLE1BQU0sWUFBWSxJQUFJLGtCQUFrQixDQUFDLENBQUM7QUFBQSxVQUNqRTtBQUlBLGlCQUFPLFlBQVk7QUFBQSxZQUNqQixJQUFJLFdBQVc7QUFBQSxjQUNiO0FBQUEsY0FBRztBQUFBLGNBQUk7QUFBQSxjQUFLO0FBQUEsY0FBSztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFJO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBSTtBQUFBLGNBQUk7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFJO0FBQUEsY0FBRztBQUFBLGNBQUs7QUFBQSxjQUMzRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBSTtBQUFBLFlBQ1osQ0FBQztBQUFBLFVBQ0g7QUFBQSxRQUNGLFNBQVMsR0FBRztBQUNWLGlCQUFPO0FBQUEsUUFDVDtBQUFBLE1BQ0Y7QUFFQSxNQUFNLGtCQUFrQixNQUFlO0FBQ3JDLFlBQUk7QUFlRixpQkFBTyxZQUFZO0FBQUEsWUFDakIsSUFBSSxXQUFXO0FBQUEsY0FDYjtBQUFBLGNBQUc7QUFBQSxjQUFJO0FBQUEsY0FBSztBQUFBLGNBQUs7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBSTtBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUk7QUFBQSxjQUFJO0FBQUEsY0FBRztBQUFBLGNBQUk7QUFBQSxjQUFHO0FBQUEsY0FBSTtBQUFBLGNBQUc7QUFBQSxjQUFLO0FBQUEsY0FBSTtBQUFBLGNBQUs7QUFBQSxjQUFJO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUM3RztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFLO0FBQUEsY0FBSztBQUFBLGNBQUc7QUFBQSxjQUFJO0FBQUEsWUFDMUQsQ0FBQztBQUFBLFVBQ0g7QUFBQSxRQUNGLFNBQVMsR0FBRztBQUNWLGlCQUFPO0FBQUEsUUFDVDtBQUFBLE1BQ0Y7QUFFQSxNQUFNLHlCQUF5QixNQUFlO0FBQzVDLFlBQUk7QUFnQkYsaUJBQU8sWUFBWTtBQUFBLFlBQ2pCLElBQUksV0FBVztBQUFBLGNBQ2I7QUFBQSxjQUFHO0FBQUEsY0FBSTtBQUFBLGNBQUs7QUFBQSxjQUFLO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUk7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUs7QUFBQSxjQUFHO0FBQUEsY0FBRztBQUFBLGNBQUc7QUFBQSxjQUFHO0FBQUEsY0FBSTtBQUFBLGNBQUk7QUFBQSxjQUFHO0FBQUEsY0FBSTtBQUFBLGNBQUc7QUFBQSxjQUFJO0FBQUEsY0FBRztBQUFBLGNBQUs7QUFBQSxjQUFJO0FBQUEsY0FBSTtBQUFBLGNBQUc7QUFBQSxjQUMxRztBQUFBLGNBQUk7QUFBQSxjQUFJO0FBQUEsY0FBRztBQUFBLGNBQUs7QUFBQSxjQUFJO0FBQUEsY0FBSztBQUFBLGNBQUs7QUFBQSxjQUFHO0FBQUEsWUFDbkMsQ0FBQztBQUFBLFVBQ0g7QUFBQSxRQUNGLFNBQVMsR0FBRztBQUNWLGlCQUFPO0FBQUEsUUFDVDtBQUFBLE1BQ0Y7QUFFTyxNQUFNLHdCQUF3QixPQUFPLFVBQStDO0FBQ3pGLFlBQUksYUFBYTtBQUNmLGlCQUFPLFFBQVEsUUFBUTtBQUFBLFFBQ3pCO0FBQ0EsWUFBSSxjQUFjO0FBQ2hCLGdCQUFNLElBQUksTUFBTSx1REFBdUQ7QUFBQSxRQUN6RTtBQUNBLFlBQUksU0FBUztBQUNYLGdCQUFNLElBQUksTUFBTSxvREFBb0Q7QUFBQSxRQUN0RTtBQUVBLHVCQUFlO0FBR2YsY0FBTSxVQUFVLE1BQU07QUFDdEIsWUFBSSxhQUFhLE1BQU07QUFHdkIsWUFBSSxNQUFNLFNBQVMsT0FBTztBQUFBLFFBRTFCLFdBQVcsTUFBTSxTQUFTLFdBQVc7QUFFbkMsY0FBSSxDQUFDLHVCQUF1QixHQUFHO0FBQzdCLGtCQUFNLElBQUksTUFBTSx1RUFBdUU7QUFBQSxVQUN6RjtBQUFBLFFBQ0YsV0FBVyxDQUFDLGdCQUFnQixHQUFHO0FBQzdCLGdCQUFNLElBQUksTUFBTSwrREFBK0Q7QUFBQSxRQUNqRjtBQUdBLGNBQU0sdUJBQXVCLHVCQUF1QjtBQUNwRCxZQUFJLGFBQWEsS0FBSyxDQUFDLHNCQUFzQjtBQUMzQyxjQUFJLE9BQU8sU0FBUyxlQUFlLENBQUMsS0FBSyxxQkFBcUI7QUFFNUQsb0JBQVE7QUFBQSxjQUNOLG1DQUNFLGFBQ0E7QUFBQSxZQUVKO0FBQUEsVUFDRjtBQUdBLGtCQUFRO0FBQUEsWUFDTjtBQUFBLFVBQ0Y7QUFHQSxnQkFBTSxhQUFhLGFBQWE7QUFBQSxRQUNsQztBQUVBLGNBQU0sWUFBWSxNQUFNO0FBQ3hCLGNBQU0scUJBQXFCLE9BQU8sY0FBYyxXQUFXLFlBQVk7QUFDdkUsY0FBTSxzQkFBdUIsV0FBaUM7QUFDOUQsY0FBTSxrQkFBbUIscUJBQTZCLFFBQVE7QUFDOUQsY0FBTSx1QkFBd0IsV0FBaUM7QUFDL0QsY0FBTSxtQkFBb0Isc0JBQThCLFFBQVE7QUFDaEUsY0FBTSxxQkFBcUIsTUFBTTtBQUVqQyxjQUFNLENBQUMsV0FBVyxjQUFjLElBQUksTUFBTSxpQkFBaUIsaUJBQWlCLG9CQUFvQixhQUFhLENBQUM7QUFFOUcsWUFBSSxZQUFZO0FBRWhCLGNBQU0sUUFBOEIsQ0FBQztBQUdyQyxZQUFJLFVBQVUsR0FBRztBQUNmLGdCQUFNO0FBQUEsWUFDSixJQUFJLFFBQVEsQ0FBQyxZQUFZO0FBQ3ZCLHlCQUFXLE1BQU07QUFDZiw0QkFBWTtBQUNaLHdCQUFRO0FBQUEsY0FDVixHQUFHLE9BQU87QUFBQSxZQUNaLENBQUM7QUFBQSxVQUNIO0FBQUEsUUFDRjtBQUdBLGNBQU07QUFBQSxVQUNKLElBQUksUUFBUSxDQUFDLFNBQVMsV0FBVztBQUMvQixrQkFBTSxTQUFpQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FLckM7QUFBQSxZQUNGO0FBRUEsZ0JBQUksb0JBQW9CO0FBRXRCLHFCQUFPLGFBQWE7QUFBQSxZQUN0QixXQUFXLG9CQUFvQixvQkFBb0I7QUFJakQscUJBQU8sYUFBYSxDQUFDLGFBQWEsb0JBQW9CLHFCQUFxQjtBQUFBLFlBQzdFLFdBQVcsbUJBQW1CLGdCQUFnQixRQUFRLE9BQU8sTUFBTSxHQUFHO0FBRXBFLHFCQUFPLGFBQWEsQ0FBQyxhQUFhLElBQUksSUFBSSxVQUFVLGVBQWUsRUFBRTtBQUFBLFlBQ3ZFLFdBQVcsV0FBVztBQUNwQixvQkFBTSx5QkFBeUIsaUNBQWlDO0FBQ2hFLGtCQUFJLHdCQUF3QjtBQUUxQix1QkFBTyxhQUFhLENBQUMsYUFBYSx5QkFBeUI7QUFBQSxjQUM3RDtBQUFBLFlBQ0Y7QUFFQSwyQkFBZSxNQUFNLEVBQUU7QUFBQTtBQUFBLGNBRXJCLENBQUMsV0FBVztBQUNWLCtCQUFlO0FBQ2YsOEJBQWM7QUFDZCx1QkFBTztBQUNQLHdCQUFRO0FBQ1Isb0JBQUksV0FBVztBQUNiLHNCQUFJLGdCQUFnQixTQUFTO0FBQUEsZ0JBQy9CO0FBQUEsY0FDRjtBQUFBO0FBQUEsY0FFQSxDQUFDLFNBQVM7QUFDUiwrQkFBZTtBQUNmLDBCQUFVO0FBQ1YsdUJBQU8sSUFBSTtBQUFBLGNBQ2I7QUFBQSxZQUNGO0FBQUEsVUFDRixDQUFDO0FBQUEsUUFDSDtBQUVBLGNBQU0sUUFBUSxLQUFLLEtBQUs7QUFFeEIsWUFBSSxXQUFXO0FBQ2IsZ0JBQU0sSUFBSSxNQUFNLDJEQUEyRCxPQUFPLElBQUk7QUFBQSxRQUN4RjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLGNBQWMsTUFBcUI7QUFDOUMsWUFBSSxlQUFlLE1BQU07QUFDdkIsaUJBQU87QUFBQSxRQUNUO0FBRUEsY0FBTSxJQUFJLE1BQU0scUNBQXFDO0FBQUEsTUFDdkQ7QUFBQTtBQUFBOzs7QUMzT0EsTUFLYSxpQkFlQSxxQkFnQ0E7QUFwRGI7QUFBQTtBQUFBO0FBR0E7QUFFTyxNQUFNLGtCQUFrQixDQUFDLE1BQWMsV0FBNkI7QUFDekUsY0FBTUMsUUFBTyxZQUFZO0FBRXpCLGNBQU0sYUFBYUEsTUFBSyxnQkFBZ0IsSUFBSSxJQUFJO0FBQ2hELGNBQU0sYUFBYUEsTUFBSyxRQUFRLFVBQVU7QUFDMUMsUUFBQUEsTUFBSyxhQUFhLE1BQU0sWUFBWSxVQUFVO0FBQzlDLGVBQU8sS0FBSyxVQUFVO0FBRXRCLGVBQU87QUFBQSxNQUNUO0FBTU8sTUFBTSxzQkFBc0IsQ0FDakMsU0FDQSxRQUNBLE1BQ0EsWUFDUztBQUNULFlBQUksT0FBTyxXQUFXLFlBQVksWUFBWSxNQUFNO0FBQ2xELGNBQUksS0FBSyxJQUFJLE9BQU8sR0FBRztBQUNyQixrQkFBTSxJQUFJLE1BQU0sK0JBQStCO0FBQUEsVUFDakQsT0FBTztBQUNMLGlCQUFLLElBQUksT0FBTztBQUFBLFVBQ2xCO0FBQUEsUUFDRjtBQUVBLGVBQU8sUUFBUSxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUMsS0FBSyxLQUFLLE1BQU07QUFDaEQsZ0JBQU0sT0FBTyxTQUFTLFNBQVMsTUFBTTtBQUNyQyxjQUFJLE9BQU8sVUFBVSxVQUFVO0FBQzdCLGdDQUFvQixPQUFrQyxPQUFPLEtBQUssTUFBTSxPQUFPO0FBQUEsVUFDakYsV0FBVyxPQUFPLFVBQVUsWUFBWSxPQUFPLFVBQVUsVUFBVTtBQUNqRSxvQkFBUSxNQUFNLE1BQU0sU0FBUyxDQUFDO0FBQUEsVUFDaEMsV0FBVyxPQUFPLFVBQVUsV0FBVztBQUNyQyxvQkFBUSxNQUFNLFFBQVEsTUFBTSxHQUFHO0FBQUEsVUFDakMsT0FBTztBQUNMLGtCQUFNLElBQUksTUFBTSxtQ0FBbUMsT0FBTyxLQUFLLEVBQUU7QUFBQSxVQUNuRTtBQUFBLFFBQ0YsQ0FBQztBQUFBLE1BQ0g7QUFNTyxNQUFNLGlCQUFpQixDQUFDLFlBQTBCO0FBQ3ZELGNBQU1BLFFBQU8sWUFBWTtBQUV6QixjQUFNLFFBQVFBLE1BQUssVUFBVTtBQUM3QixZQUFJO0FBQ0YsZ0JBQU0sVUFBVUEsTUFBSztBQUNyQixnQkFBTSxlQUFlQSxNQUFLLFdBQVcsSUFBSSxPQUFPO0FBQ2hELFVBQUFBLE1BQUssaUJBQWlCLGNBQWMsZUFBZSxPQUFPO0FBQzFELGdCQUFNLFlBQVksT0FBT0EsTUFBSyxTQUFTLGNBQWMsWUFBWSxJQUFJLFFBQVEsS0FBSyxDQUFDO0FBQ25GLGdCQUFNLHNCQUFzQkEsTUFBSyxTQUFTLGVBQWUsU0FBUyxHQUFHO0FBQ3JFLGdCQUFNLGVBQWUsc0JBQXNCQSxNQUFLLGFBQWEsbUJBQW1CLElBQUk7QUFDcEYsZ0JBQU0sSUFBSSxNQUFNLEdBQUcsT0FBTyxnQkFBZ0IsU0FBUyxvQkFBb0IsWUFBWSxFQUFFO0FBQUEsUUFDdkYsVUFBRTtBQUNBLFVBQUFBLE1BQUssYUFBYSxLQUFLO0FBQUEsUUFDekI7QUFBQSxNQUNGO0FBQUE7QUFBQTs7O0FDbkVBLE1BUWE7QUFSYjtBQUFBO0FBQUE7QUFLQTtBQUNBO0FBRU8sTUFBTSxnQkFBZ0IsQ0FBQyxZQUE2RDtBQUN6RixjQUFNQyxRQUFPLFlBQVk7QUFDekIsWUFBSSxtQkFBbUI7QUFDdkIsY0FBTSxTQUFtQixDQUFDO0FBRTFCLGNBQU0sYUFBMEMsV0FBVyxDQUFDO0FBRTVELFlBQUk7QUFDRixjQUFJLFNBQVMscUJBQXFCLFFBQVc7QUFDM0MsdUJBQVcsbUJBQW1CO0FBQUEsVUFDaEMsV0FDRSxPQUFPLFFBQVEscUJBQXFCLFlBQ3BDLENBQUMsT0FBTyxVQUFVLFFBQVEsZ0JBQWdCLEtBQzFDLFFBQVEsbUJBQW1CLEtBQzNCLFFBQVEsbUJBQW1CLEdBQzNCO0FBQ0Esa0JBQU0sSUFBSSxNQUFNLHFDQUFxQyxRQUFRLGdCQUFnQixFQUFFO0FBQUEsVUFDakY7QUFFQSxjQUFJLFNBQVMsc0JBQXNCLFFBQVc7QUFDNUMsdUJBQVcsb0JBQW9CO0FBQUEsVUFDakMsV0FBVyxPQUFPLFFBQVEsc0JBQXNCLFlBQVksQ0FBQyxPQUFPLFVBQVUsUUFBUSxpQkFBaUIsR0FBRztBQUN4RyxrQkFBTSxJQUFJLE1BQU0scUNBQXFDLFFBQVEsaUJBQWlCLEVBQUU7QUFBQSxVQUNsRjtBQUVBLGNBQUksU0FBUyxjQUFjLFFBQVc7QUFDcEMsdUJBQVcsWUFBWTtBQUFBLFVBQ3pCO0FBRUEsY0FBSSxnQkFBZ0I7QUFDcEIsY0FBSSxTQUFTLFFBQVEsUUFBVztBQUM5Qiw0QkFBZ0IsZ0JBQWdCLFFBQVEsS0FBSyxNQUFNO0FBQUEsVUFDckQ7QUFFQSw2QkFBbUJBLE1BQUs7QUFBQSxZQUN0QixXQUFXO0FBQUEsWUFDWCxXQUFXO0FBQUEsWUFDWCxDQUFDLENBQUMsV0FBVztBQUFBLFlBQ2I7QUFBQSxVQUNGO0FBQ0EsY0FBSSxxQkFBcUIsR0FBRztBQUMxQiwyQkFBZSwyQkFBMkI7QUFBQSxVQUM1QztBQUVBLGNBQUksU0FBUyxVQUFVLFFBQVc7QUFDaEMsZ0NBQW9CLFFBQVEsT0FBTyxJQUFJLG9CQUFJLFFBQWlDLEdBQUcsQ0FBQyxLQUFLLFVBQVU7QUFDN0Ysb0JBQU0sZ0JBQWdCLGdCQUFnQixLQUFLLE1BQU07QUFDakQsb0JBQU0sa0JBQWtCLGdCQUFnQixPQUFPLE1BQU07QUFFckQsa0JBQUlBLE1BQUssc0JBQXNCLGtCQUFrQixlQUFlLGVBQWUsTUFBTSxHQUFHO0FBQ3RGLCtCQUFlLGlDQUFpQyxHQUFHLE1BQU0sS0FBSyxHQUFHO0FBQUEsY0FDbkU7QUFBQSxZQUNGLENBQUM7QUFBQSxVQUNIO0FBRUEsaUJBQU8sQ0FBQyxrQkFBa0IsTUFBTTtBQUFBLFFBQ2xDLFNBQVMsR0FBRztBQUNWLGNBQUkscUJBQXFCLEdBQUc7QUFDMUIsWUFBQUEsTUFBSyxzQkFBc0IsZ0JBQWdCO0FBQUEsVUFDN0M7QUFDQSxpQkFBTyxRQUFRLENBQUMsVUFBVUEsTUFBSyxNQUFNLEtBQUssQ0FBQztBQUMzQyxnQkFBTTtBQUFBLFFBQ1I7QUFBQSxNQUNGO0FBQUE7QUFBQTs7O0FDdkVBLE1BUU0sMEJBZUEsa0JBV0Esc0JBc0JBLHFCQWNBLHVCQStGTztBQXJLYjtBQUFBO0FBQUE7QUFLQTtBQUNBO0FBRUEsTUFBTSwyQkFBMkIsQ0FBQywyQkFBcUQ7QUFDckYsZ0JBQVEsd0JBQXdCO0FBQUEsVUFDOUIsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVDtBQUNFLGtCQUFNLElBQUksTUFBTSx5Q0FBeUMsc0JBQXNCLEVBQUU7QUFBQSxRQUNyRjtBQUFBLE1BQ0Y7QUFFQSxNQUFNLG1CQUFtQixDQUFDLGtCQUFxRDtBQUM3RSxnQkFBUSxlQUFlO0FBQUEsVUFDckIsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNUO0FBQ0Usa0JBQU0sSUFBSSxNQUFNLCtCQUErQixhQUFhLEVBQUU7QUFBQSxRQUNsRTtBQUFBLE1BQ0Y7QUFFQSxNQUFNLHVCQUF1QixDQUFDLFlBQW1EO0FBQy9FLFlBQUksQ0FBQyxRQUFRLE9BQU87QUFDbEIsa0JBQVEsUUFBUSxDQUFDO0FBQUEsUUFDbkI7QUFDQSxZQUFJLENBQUMsUUFBUSxNQUFNLFNBQVM7QUFDMUIsa0JBQVEsTUFBTSxVQUFVLENBQUM7QUFBQSxRQUMzQjtBQUNBLGNBQU0sVUFBVSxRQUFRLE1BQU07QUFDOUIsWUFBSSxDQUFDLFFBQVEsOEJBQThCO0FBRXpDLGtCQUFRLCtCQUErQjtBQUFBLFFBQ3pDO0FBR0EsWUFDRSxRQUFRLHNCQUNSLFFBQVEsbUJBQW1CLEtBQUssQ0FBQyxRQUFRLE9BQU8sT0FBTyxXQUFXLEtBQUssR0FBRyxVQUFVLFFBQVEsR0FDNUY7QUFDQSxrQkFBUSxtQkFBbUI7QUFBQSxRQUM3QjtBQUFBLE1BQ0Y7QUFFQSxNQUFNLHNCQUFzQixDQUFDLHNCQUE4QixLQUFhLE9BQWUsV0FBMkI7QUFDaEgsY0FBTSxnQkFBZ0IsZ0JBQWdCLEtBQUssTUFBTTtBQUNqRCxjQUFNLGtCQUFrQixnQkFBZ0IsT0FBTyxNQUFNO0FBQ3JELFlBQUksWUFBWSxFQUFFLDBCQUEwQixzQkFBc0IsZUFBZSxlQUFlLE1BQU0sR0FBRztBQUN2Ryx5QkFBZSxxQ0FBcUMsR0FBRyxNQUFNLEtBQUssR0FBRztBQUFBLFFBQ3ZFO0FBQUEsTUFDRjtBQVFBLE1BQU0sd0JBQXdCLE9BQzVCLHNCQUNBLG9CQUNBLFdBQ2tCO0FBQ2xCLG1CQUFXLE1BQU0sb0JBQW9CO0FBQ25DLGNBQUksU0FBUyxPQUFPLE9BQU8sV0FBVyxLQUFLLEdBQUc7QUFDOUMsZ0JBQU0sWUFBcUMsQ0FBQztBQUc1QyxrQkFBUSxRQUFRO0FBQUEsWUFDZCxLQUFLO0FBQ0gsdUJBQVM7QUFDVCxrQkFBSSxPQUFPLE9BQU8sVUFBVTtBQUMxQixzQkFBTSxlQUFlO0FBRXJCLHNCQUFNLGFBQWMsY0FBdUQ7QUFDM0Usb0JBQUksWUFBWTtBQUNkLHNDQUFvQixzQkFBc0IsY0FBYyxZQUFZLE1BQU07QUFBQSxnQkFDNUU7QUFBQSxjQUNGO0FBQ0E7QUFBQSxZQUNGLEtBQUs7QUFDSCxrQkFBSSxPQUEwQjtBQUM1Qix5QkFBUztBQUNULG9CQUFJO0FBRUosb0JBQUksT0FBTyxPQUFPLFVBQVU7QUFDMUIsd0JBQU0sZ0JBQWdCO0FBQ3RCLHNCQUFJLGNBQWMsUUFBUTtBQUN4Qix3QkFBSSxPQUFPLGNBQWMsZUFBZSxjQUFjLGtCQUFrQixXQUFXO0FBQ2pGLHFDQUFlLGNBQWM7QUFBQSxvQkFDL0IsT0FBTztBQUNMLDRCQUFNLElBQUksTUFBTSw4Q0FBOEM7QUFBQSxvQkFDaEU7QUFBQSxrQkFDRjtBQUFBLGdCQUdGO0FBRUEsc0JBQU0sT0FBTyxZQUFZLEVBQUUscUJBQXNCLFlBQVk7QUFDN0Qsb0JBQUksTUFBTTtBQUNSLHdCQUFNLENBQUMsVUFBVSxnQkFBZ0IsWUFBWSxJQUFJO0FBQ2pELGlDQUFlLFdBQVcsWUFBWSxTQUFTLFNBQVMsR0FBRyxNQUFNO0FBQ2pFLGlDQUFlLFdBQVcsa0JBQWtCLGVBQWUsU0FBUyxHQUFHLE1BQU07QUFDN0UsaUNBQWUsV0FBVyxnQkFBZ0IsYUFBYSxTQUFTLEdBQUcsTUFBTTtBQUFBLGdCQUMzRTtBQUFBLGNBQ0YsT0FBTztBQUNMLHlCQUFTO0FBQ1Qsb0JBQUksT0FBTyxPQUFPLFVBQVU7QUFDMUIsd0JBQU0sZ0JBQWdCO0FBQ3RCLHNCQUFJLGVBQWUsaUJBQWlCO0FBQ2xDLHdCQUFJLGNBQWMsb0JBQW9CLFVBQVUsY0FBYyxvQkFBb0IsUUFBUTtBQUN4Riw0QkFBTSxJQUFJLE1BQU0sb0RBQW9ELGNBQWMsZUFBZSxFQUFFO0FBQUEsb0JBQ3JHO0FBQ0Esd0NBQW9CLHNCQUFzQixtQkFBbUIsY0FBYyxpQkFBaUIsTUFBTTtBQUFBLGtCQUNwRztBQUFBLGdCQUNGO0FBQUEsY0FDRjtBQUNBO0FBQUEsWUFDRixLQUFLO0FBQUEsWUFDTCxLQUFLO0FBQ0g7QUFBQSxZQUNGO0FBQ0Usb0JBQU0sSUFBSSxNQUFNLHFDQUFxQyxNQUFNLEVBQUU7QUFBQSxVQUNqRTtBQUVBLGdCQUFNLG1CQUFtQixnQkFBZ0IsUUFBUSxNQUFNO0FBQ3ZELGdCQUFNLGlCQUFpQixVQUFVO0FBQ2pDLGNBQUksYUFBYTtBQUNqQixjQUFJLGVBQWU7QUFDbkIsY0FBSSxpQkFBaUIsR0FBRztBQUN0Qix5QkFBYSxZQUFZLEVBQUUsUUFBUSxpQkFBaUIsWUFBWSxFQUFFLFFBQVE7QUFDMUUsbUJBQU8sS0FBSyxVQUFVO0FBQ3RCLDJCQUFlLFlBQVksRUFBRSxRQUFRLGlCQUFpQixZQUFZLEVBQUUsUUFBUTtBQUM1RSxtQkFBTyxLQUFLLFlBQVk7QUFDeEIscUJBQVMsSUFBSSxHQUFHLElBQUksZ0JBQWdCLEtBQUs7QUFDdkMsMEJBQVksRUFBRSxTQUFTLGFBQWEsSUFBSSxZQUFZLEVBQUUsVUFBVSxVQUFVLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRztBQUNwRiwwQkFBWSxFQUFFLFNBQVMsZUFBZSxJQUFJLFlBQVksRUFBRSxVQUFVLFVBQVUsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHO0FBQUEsWUFDeEY7QUFBQSxVQUNGO0FBQ0EsY0FDRyxNQUFNLFlBQVksRUFBRTtBQUFBLFlBQ25CO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFVBQ0YsTUFBTyxHQUNQO0FBQ0EsMkJBQWUsb0NBQW9DLE1BQU0sR0FBRztBQUFBLFVBQzlEO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLG9CQUFvQixPQUFPLFlBQTJFO0FBQ2pILGNBQU1DLFFBQU8sWUFBWTtBQUN6QixZQUFJLHVCQUF1QjtBQUMzQixjQUFNLFNBQW1CLENBQUM7QUFFMUIsY0FBTSxpQkFBa0QsV0FBVyxDQUFDO0FBQ3BFLDZCQUFxQixjQUFjO0FBRW5DLFlBQUk7QUFDRixnQkFBTSx5QkFBeUIseUJBQXlCLGVBQWUsMEJBQTBCLEtBQUs7QUFDdEcsZ0JBQU0sZ0JBQWdCLGlCQUFpQixlQUFlLGlCQUFpQixZQUFZO0FBQ25GLGdCQUFNLGtCQUNKLE9BQU8sZUFBZSxVQUFVLFdBQVcsZ0JBQWdCLGVBQWUsT0FBTyxNQUFNLElBQUk7QUFFN0YsZ0JBQU0sbUJBQW1CLGVBQWUsb0JBQW9CO0FBQzVELGNBQUksQ0FBQyxPQUFPLFVBQVUsZ0JBQWdCLEtBQUssbUJBQW1CLEtBQUssbUJBQW1CLEdBQUc7QUFDdkYsa0JBQU0sSUFBSSxNQUFNLHFDQUFxQyxnQkFBZ0IsRUFBRTtBQUFBLFVBQ3pFO0FBRUEsZ0JBQU0sb0JBQW9CLGVBQWUscUJBQXFCO0FBQzlELGNBQUksQ0FBQyxPQUFPLFVBQVUsaUJBQWlCLEtBQUssb0JBQW9CLEtBQUssb0JBQW9CLEdBQUc7QUFDMUYsa0JBQU0sSUFBSSxNQUFNLHFDQUFxQyxpQkFBaUIsRUFBRTtBQUFBLFVBQzFFO0FBRUEsZ0JBQU0sK0JBQ0osT0FBTyxlQUFlLDJCQUEyQixXQUM3QyxnQkFBZ0IsZUFBZSx3QkFBd0IsTUFBTSxJQUM3RDtBQUVOLGlDQUF1QkEsTUFBSztBQUFBLFlBQzFCO0FBQUEsWUFDQSxDQUFDLENBQUMsZUFBZTtBQUFBLFlBQ2pCLENBQUMsQ0FBQyxlQUFlO0FBQUEsWUFDakI7QUFBQSxZQUNBLENBQUMsQ0FBQyxlQUFlO0FBQUEsWUFDakI7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUNBLGNBQUkseUJBQXlCLEdBQUc7QUFDOUIsMkJBQWUsK0JBQStCO0FBQUEsVUFDaEQ7QUFFQSxjQUFJLGVBQWUsb0JBQW9CO0FBQ3JDLGtCQUFNLHNCQUFzQixzQkFBc0IsZUFBZSxvQkFBb0IsTUFBTTtBQUFBLFVBQzdGO0FBRUEsY0FBSSxlQUFlLHVCQUF1QixRQUFXO0FBQ25ELGdCQUFJLE9BQU8sZUFBZSx1QkFBdUIsV0FBVztBQUMxRCxvQkFBTSxJQUFJLE1BQU0sK0NBQStDLGVBQWUsa0JBQWtCLEVBQUU7QUFBQSxZQUNwRztBQUNBO0FBQUEsY0FDRTtBQUFBLGNBQ0E7QUFBQSxjQUNBLGVBQWUsbUJBQW1CLFNBQVM7QUFBQSxjQUMzQztBQUFBLFlBQ0Y7QUFBQSxVQUNGO0FBRUEsY0FBSSxlQUFlLHdCQUF3QjtBQUN6Qyx1QkFBVyxDQUFDLE1BQU0sS0FBSyxLQUFLLE9BQU8sUUFBUSxlQUFlLHNCQUFzQixHQUFHO0FBQ2pGLGtCQUFJLE9BQU8sU0FBUyxVQUFVO0FBQzVCLHNCQUFNLElBQUksTUFBTSxrREFBa0QsSUFBSSxFQUFFO0FBQUEsY0FDMUU7QUFDQSxrQkFBSSxPQUFPLFVBQVUsWUFBWSxDQUFDLE9BQU8sVUFBVSxLQUFLLEtBQUssUUFBUSxHQUFHO0FBQ3RFLHNCQUFNLElBQUksTUFBTSxpRUFBaUUsS0FBSyxFQUFFO0FBQUEsY0FDMUY7QUFDQSxvQkFBTSxhQUFhLGdCQUFnQixNQUFNLE1BQU07QUFDL0Msa0JBQUlBLE1BQUssNkJBQTZCLHNCQUFzQixZQUFZLEtBQUssTUFBTSxHQUFHO0FBQ3BGLCtCQUFlLHdDQUF3QyxJQUFJLE1BQU0sS0FBSyxHQUFHO0FBQUEsY0FDM0U7QUFBQSxZQUNGO0FBQUEsVUFDRjtBQUVBLGNBQUksZUFBZSxVQUFVLFFBQVc7QUFDdEMsZ0NBQW9CLGVBQWUsT0FBTyxJQUFJLG9CQUFJLFFBQWlDLEdBQUcsQ0FBQyxLQUFLLFVBQVU7QUFDcEcsa0NBQW9CLHNCQUFzQixLQUFLLE9BQU8sTUFBTTtBQUFBLFlBQzlELENBQUM7QUFBQSxVQUNIO0FBRUEsaUJBQU8sQ0FBQyxzQkFBc0IsTUFBTTtBQUFBLFFBQ3RDLFNBQVMsR0FBRztBQUNWLGNBQUkseUJBQXlCLEdBQUc7QUFDOUIsZ0JBQUlBLE1BQUssMEJBQTBCLG9CQUFvQixNQUFNLEdBQUc7QUFDOUQsNkJBQWUsZ0NBQWdDO0FBQUEsWUFDakQ7QUFBQSxVQUNGO0FBQ0EsaUJBQU8sUUFBUSxDQUFDLFVBQVVBLE1BQUssTUFBTSxLQUFLLENBQUM7QUFDM0MsZ0JBQU07QUFBQSxRQUNSO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQ2pRQSxNQTJDYSw0QkF5Q0EsNEJBMENBLDRCQXFDQSxtQ0FnREEsc0JBb0JBLDBCQWNBLHlCQWdCQTtBQXJRYjtBQUFBO0FBQUE7QUEyQ08sTUFBTSw2QkFBNkIsQ0FBQyxTQUEyQjtBQUNwRSxnQkFBUSxNQUFNO0FBQUEsVUFDWixLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFFVDtBQUNFLGtCQUFNLElBQUksTUFBTSwwQkFBMEIsSUFBSSxFQUFFO0FBQUEsUUFDcEQ7QUFBQSxNQUNGO0FBS08sTUFBTSw2QkFBNkIsQ0FBQyxjQUFxQztBQUM5RSxnQkFBUSxXQUFXO0FBQUEsVUFDakIsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBRVQ7QUFDRSxrQkFBTSxJQUFJLE1BQU0sMEJBQTBCLFNBQVMsRUFBRTtBQUFBLFFBQ3pEO0FBQUEsTUFDRjtBQU1PLE1BQU0sNkJBQTZCLENBQ3hDLFVBQ0EsZUFDdUI7QUFDdkIsY0FBTSxjQUFjO0FBQUEsVUFDbEI7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFFBQ0YsRUFBRSxRQUFRO0FBRVYsY0FBTSxPQUFPLE9BQU8sZUFBZSxXQUFXLGFBQWEsV0FBVyxPQUFPLENBQUMsR0FBRyxNQUFNLElBQUksR0FBRyxDQUFDO0FBQy9GLGVBQU8sY0FBYyxJQUFJLEtBQUssS0FBSyxPQUFPLFdBQVcsSUFBSTtBQUFBLE1BQzNEO0FBS08sTUFBTSxvQ0FBb0MsQ0FDL0MsU0FZK0I7QUFDL0IsZ0JBQVEsTUFBTTtBQUFBLFVBQ1osS0FBSztBQUVILG1CQUFPLE9BQU8saUJBQWlCLGVBQWUsYUFBYSxPQUFPLGVBQWU7QUFBQSxVQUNuRixLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1Q7QUFDRSxrQkFBTSxJQUFJLE1BQU0scUJBQXFCLElBQUksRUFBRTtBQUFBLFFBQy9DO0FBQUEsTUFDRjtBQUtPLE1BQU0sdUJBQXVCLENBQUMsYUFBMEU7QUFDN0csZ0JBQVEsVUFBVTtBQUFBLFVBQ2hCLEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVDtBQUNFLGtCQUFNLElBQUksTUFBTSw4QkFBOEIsUUFBUSxFQUFFO0FBQUEsUUFDNUQ7QUFBQSxNQUNGO0FBS08sTUFBTSwyQkFBMkIsQ0FBQyxTQUN2QyxTQUFTLGFBQ1QsU0FBUyxhQUNULFNBQVMsV0FDVCxTQUFTLFdBQ1QsU0FBUyxZQUNULFNBQVMsV0FDVCxTQUFTLFVBQ1QsU0FBUyxXQUNULFNBQVM7QUFLSixNQUFNLDBCQUEwQixDQUFDLFNBQ3RDLFNBQVMsYUFDVCxTQUFTLGFBQ1QsU0FBUyxXQUNULFNBQVMsV0FDVCxTQUFTLFlBQ1QsU0FBUyxZQUNULFNBQVMsVUFDVCxTQUFTLFdBQ1QsU0FBUyxVQUNULFNBQVMsV0FDVCxTQUFTO0FBS0osTUFBTSwyQkFBMkIsQ0FBQ0MsY0FBMEM7QUFDakYsZ0JBQVFBLFdBQVU7QUFBQSxVQUNoQixLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVDtBQUNFLGtCQUFNLElBQUksTUFBTSw4QkFBOEJBLFNBQVEsRUFBRTtBQUFBLFFBQzVEO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQ3RSQSxNQVdhO0FBWGI7QUFBQTtBQUFBO0FBR0E7QUFRTyxNQUFNLFdBQVcsT0FBTyxTQUE0RTtBQUN6RyxZQUFJLE9BQU8sU0FBUyxVQUFVO0FBQzVCLGNBQUksUUFBUTtBQUVWLGdCQUFJO0FBQ0Ysb0JBQU0sRUFBRSxTQUFTLElBQUksVUFBUSxrQkFBa0I7QUFDL0MscUJBQU8sSUFBSSxXQUFXLE1BQU0sU0FBUyxJQUFJLENBQUM7QUFBQSxZQUM1QyxTQUFTLEdBQUc7QUFDVixrQkFBSSxFQUFFLFNBQVMseUJBQXlCO0FBRXRDLHNCQUFNLEVBQUUsaUJBQWlCLElBQUksVUFBUSxTQUFTO0FBQzlDLHNCQUFNLFNBQVMsaUJBQWlCLElBQUk7QUFDcEMsc0JBQU0sU0FBdUIsQ0FBQztBQUM5QixpQ0FBaUIsU0FBUyxRQUFRO0FBQ2hDLHlCQUFPLEtBQUssS0FBSztBQUFBLGdCQUNuQjtBQUNBLHVCQUFPLElBQUksV0FBVyxPQUFPLE9BQU8sTUFBTSxDQUFDO0FBQUEsY0FDN0M7QUFDQSxvQkFBTTtBQUFBLFlBQ1I7QUFBQSxVQUNGLE9BQU87QUFFTCxrQkFBTSxXQUFXLE1BQU0sTUFBTSxJQUFJO0FBQ2pDLGdCQUFJLENBQUMsU0FBUyxJQUFJO0FBQ2hCLG9CQUFNLElBQUksTUFBTSxzQ0FBc0MsSUFBSSxFQUFFO0FBQUEsWUFDOUQ7QUFDQSxrQkFBTSxzQkFBc0IsU0FBUyxRQUFRLElBQUksZ0JBQWdCO0FBQ2pFLGtCQUFNLFdBQVcsc0JBQXNCLFNBQVMscUJBQXFCLEVBQUUsSUFBSTtBQUMzRSxnQkFBSSxXQUFXLFlBQXNCO0FBR25DLHFCQUFPLElBQUksV0FBVyxNQUFNLFNBQVMsWUFBWSxDQUFDO0FBQUEsWUFDcEQsT0FBTztBQUVMLGtCQUFJLENBQUMsU0FBUyxNQUFNO0FBQ2xCLHNCQUFNLElBQUksTUFBTSxzQ0FBc0MsSUFBSSxxQkFBcUI7QUFBQSxjQUNqRjtBQUNBLG9CQUFNLFNBQVMsU0FBUyxLQUFLLFVBQVU7QUFFdkMsa0JBQUk7QUFDSixrQkFBSTtBQUVGLHlCQUFTLElBQUksWUFBWSxRQUFRO0FBQUEsY0FDbkMsU0FBUyxHQUFHO0FBQ1Ysb0JBQUksYUFBYSxZQUFZO0FBRTNCLHdCQUFNLFFBQVEsS0FBSyxLQUFLLFdBQVcsS0FBSztBQUN4QywyQkFBUyxJQUFJLFlBQVksT0FBTyxFQUFFLFNBQVMsT0FBTyxTQUFTLE1BQU0sQ0FBQyxFQUFFO0FBQUEsZ0JBQ3RFLE9BQU87QUFDTCx3QkFBTTtBQUFBLGdCQUNSO0FBQUEsY0FDRjtBQUVBLGtCQUFJLFNBQVM7QUFFYixxQkFBTyxNQUFNO0FBQ1gsc0JBQU0sRUFBRSxNQUFNLE1BQU0sSUFBSSxNQUFNLE9BQU8sS0FBSztBQUMxQyxvQkFBSSxNQUFNO0FBQ1I7QUFBQSxnQkFDRjtBQUNBLHNCQUFNLFlBQVksTUFBTTtBQUN4QixzQkFBTSxRQUFRLElBQUksV0FBVyxRQUFRLFFBQVEsU0FBUztBQUN0RCxzQkFBTSxJQUFJLEtBQUs7QUFDZiwwQkFBVTtBQUFBLGNBQ1o7QUFDQSxxQkFBTyxJQUFJLFdBQVcsUUFBUSxHQUFHLFFBQVE7QUFBQSxZQUMzQztBQUFBLFVBQ0Y7QUFBQSxRQUNGLFdBQVcsZ0JBQWdCLE1BQU07QUFDL0IsaUJBQU8sSUFBSSxXQUFXLE1BQU0sS0FBSyxZQUFZLENBQUM7QUFBQSxRQUNoRCxXQUFXLGdCQUFnQixZQUFZO0FBQ3JDLGlCQUFPO0FBQUEsUUFDVCxPQUFPO0FBQ0wsaUJBQU8sSUFBSSxXQUFXLElBQUk7QUFBQSxRQUM1QjtBQUFBLE1BQ0Y7QUFBQTtBQUFBOzs7QUN0RkEsTUFZTSxnQkFFQSxPQUtGLGdCQUNBLE9BRVMsaUJBUUEsS0FXQTtBQXpDYjtBQUFBO0FBQUE7QUFLQTtBQU9BLE1BQU0saUJBQWlCLENBQUMsS0FBSyxLQUFLLEtBQUssS0FBSyxHQUFHO0FBRS9DLE1BQU0sUUFBUSxDQUFDLE9BQWUsWUFBMEI7QUFFdEQsZ0JBQVEsSUFBSSxJQUFJLGVBQWUsS0FBSyxDQUFDLEtBQUksb0JBQUksS0FBSyxHQUFFLFlBQVksQ0FBQyxJQUFJLE9BQU8sRUFBRTtBQUFBLE1BQ2hGO0FBS08sTUFBTSxrQkFBa0IsQ0FBQyxpQkFBMkIsV0FBMEI7QUFDbkYseUJBQWlCO0FBQ2pCLGdCQUFRO0FBQUEsTUFDVjtBQUtPLE1BQU0sTUFBTSxDQUFDLFVBQW9CLFFBQXVCO0FBQzdELGNBQU0sZUFBZSxxQkFBcUIsUUFBUTtBQUNsRCxjQUFNLGNBQWMscUJBQXFCLGNBQWM7QUFDdkQsWUFBSSxnQkFBZ0IsYUFBYTtBQUMvQixnQkFBTSxjQUFjLE9BQU8sUUFBUSxhQUFhLElBQUksSUFBSSxHQUFHO0FBQUEsUUFDN0Q7QUFBQSxNQUNGO0FBS08sTUFBTSxZQUF3QixJQUFJLFNBQWlDO0FBQ3hFLFlBQUksT0FBTztBQUNULGNBQUksR0FBRyxJQUFJO0FBQUEsUUFDYjtBQUFBLE1BQ0Y7QUFBQTtBQUFBOzs7QUM3Q0EsTUFLYSxZQVlBLGVBa0ZBLFdBOElBLGNBc1FBLFVBcURBLFVBQ0E7QUE3aUJiO0FBQUE7QUFBQTtBQUtPLE1BQU0sYUFBTixNQUFpQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBT3RCLE9BQU8sZ0JBQWdCLEdBQXFCLEdBQW1EO0FBQzdGLGlCQUFPLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLFNBQVksQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztBQUFBLFFBQ2hEO0FBQUEsTUFDRjtBQUVPLE1BQU0sZ0JBQU4sTUFBb0I7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBUXpCLE9BQU8sVUFDTCxPQUNBLE9BQ0EsV0FBVyxPQUNvQjtBQUMvQixnQkFBTSxRQUFRLE1BQU07QUFDcEIsZ0JBQU0sUUFBUSxNQUFNO0FBQ3BCLGNBQUksVUFBVSxHQUFHO0FBQ2YsbUJBQU87QUFBQSxVQUNUO0FBQ0EsY0FBSSxVQUFVLEdBQUc7QUFDZixtQkFBTztBQUFBLFVBQ1Q7QUFDQSxnQkFBTSxRQUFRLEtBQUssSUFBSSxNQUFNLFFBQVEsTUFBTSxNQUFNO0FBQ2pELGdCQUFNLFFBQVEsSUFBSSxNQUFjLEtBQUs7QUFHckMsY0FBSSxVQUFVO0FBQ1osZ0JBQUksUUFBUSxLQUFLLFFBQVEsR0FBRztBQUMxQixxQkFBTztBQUFBLFlBQ1Q7QUFDQSxrQkFBTSxlQUFlLFdBQVc7QUFBQSxjQUM5QixDQUFDLE1BQU0sUUFBUSxDQUFDLEdBQUcsTUFBTSxRQUFRLENBQUMsQ0FBQztBQUFBLGNBQ25DLENBQUMsTUFBTSxRQUFRLENBQUMsR0FBRyxNQUFNLFFBQVEsQ0FBQyxDQUFDO0FBQUEsWUFDckM7QUFDQSxnQkFBSSxpQkFBaUIsUUFBVztBQUM5QixxQkFBTztBQUFBLFlBQ1Q7QUFDQSxhQUFDLE1BQU0sUUFBUSxDQUFDLEdBQUcsTUFBTSxRQUFRLENBQUMsQ0FBQyxJQUFJO0FBQUEsVUFDekM7QUFFQSxtQkFBUyxJQUFJLFdBQVcsSUFBSSxHQUFHLEtBQUssT0FBTyxLQUFLO0FBQzlDLGtCQUFNLE9BQU8sUUFBUSxJQUFJLElBQUksSUFBSSxNQUFNLFFBQVEsQ0FBQztBQUNoRCxrQkFBTSxPQUFPLFFBQVEsSUFBSSxJQUFJLElBQUksTUFBTSxRQUFRLENBQUM7QUFFaEQsZ0JBQUksU0FBUyxRQUFRLE9BQU8sS0FBSyxPQUFPLEdBQUc7QUFDekMscUJBQU87QUFBQSxZQUNUO0FBQ0Esa0JBQU0sTUFBTSxLQUFLLElBQUksTUFBTSxJQUFJO0FBQy9CLGdCQUFJLFFBQVEsTUFBTTtBQUNoQixvQkFBTSxRQUFRLENBQUMsSUFBSSxLQUFLLElBQUksTUFBTSxJQUFJO0FBQUEsWUFDeEMsT0FBTztBQUVMLGtCQUFJLE1BQU0sR0FBRztBQUNYLHVCQUFPO0FBQUEsY0FDVDtBQUNBLG9CQUFNLFFBQVEsQ0FBQyxJQUFJO0FBQUEsWUFDckI7QUFBQSxVQUNGO0FBRUEsaUJBQU87QUFBQSxRQUNUO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBT0EsT0FBTyxpQkFBaUIsT0FBMEIsWUFBd0M7QUFFeEYsZ0JBQU0sWUFBWSxNQUFNO0FBQ3hCLGdCQUFNLFlBQVksV0FBVztBQUM3QixjQUFJLFlBQVksV0FBVztBQUN6QixtQkFBTztBQUFBLFVBQ1Q7QUFDQSxtQkFBUyxJQUFJLEdBQUcsS0FBSyxXQUFXLEtBQUs7QUFDbkMsZ0JBQUksTUFBTSxZQUFZLENBQUMsTUFBTSxLQUFLLE1BQU0sWUFBWSxDQUFDLE1BQU0sV0FBVyxZQUFZLENBQUMsR0FBRztBQUNwRixxQkFBTztBQUFBLFlBQ1Q7QUFBQSxVQUNGO0FBQ0EsaUJBQU87QUFBQSxRQUNUO0FBQUEsTUFDRjtBQUVPLE1BQU0sWUFBTixNQUFNLFdBQVU7QUFBQTtBQUFBO0FBQUE7QUFBQSxRQUlyQixPQUFPLEtBQUssTUFBaUM7QUFDM0MsaUJBQU8sV0FBVSwwQkFBMEIsTUFBTSxHQUFHLEtBQUssTUFBTTtBQUFBLFFBQ2pFO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFLQSxPQUFPLGFBQWEsTUFBeUIsT0FBTyxHQUFzQjtBQUN4RSxnQkFBTSxPQUFPLEtBQUs7QUFDbEIsY0FBSSxTQUFTLEdBQUc7QUFDZCxtQkFBTyxDQUFDO0FBQUEsVUFDVjtBQUNBLGdCQUFNLFVBQVUsSUFBSSxNQUFNLElBQUk7QUFDOUIsY0FBSSxJQUFJLE9BQU87QUFDZixpQkFBTyxLQUFLLEdBQUc7QUFDYixnQkFBSSxLQUFLLENBQUMsSUFBSSxTQUFTLEdBQUc7QUFDeEIsc0JBQVEsQ0FBQyxJQUFJLEtBQUssQ0FBQyxJQUFJO0FBQ3ZCO0FBQUEsWUFDRjtBQUNBLGdCQUFJLE9BQU8sS0FBSyxDQUFDLE1BQU0sR0FBRztBQUN4QixvQkFBTSxJQUFJLE1BQU0sc0JBQXNCO0FBQUEsWUFDeEM7QUFDQSxvQkFBUSxDQUFDLElBQUk7QUFDYixvQkFBUSxLQUFLLENBQUM7QUFDZDtBQUFBLFVBQ0Y7QUFDQSxlQUFLLEtBQUssS0FBSyxHQUFHLEtBQUs7QUFDckIsb0JBQVEsQ0FBQyxJQUFJLEtBQUssQ0FBQztBQUFBLFVBQ3JCO0FBQ0EsaUJBQU87QUFBQSxRQUNUO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFLQSxPQUFPLGtCQUFrQixNQUF5QixNQUFzQjtBQUN0RSxjQUFJLE9BQU8sS0FBSyxPQUFPLEtBQUssUUFBUTtBQUNsQyxrQkFBTSxJQUFJLE1BQU0sd0JBQXdCLElBQUksd0NBQXdDLEtBQUssTUFBTSxjQUFjO0FBQUEsVUFDL0c7QUFDQSxpQkFBTyxXQUFVLDBCQUEwQixNQUFNLE1BQU0sS0FBSyxNQUFNO0FBQUEsUUFDcEU7QUFBQTtBQUFBO0FBQUE7QUFBQSxRQUtBLE9BQU8sZ0JBQWdCLE1BQXlCLE1BQXNCO0FBQ3BFLGNBQUksT0FBTyxLQUFLLE9BQU8sS0FBSyxRQUFRO0FBQ2xDLGtCQUFNLElBQUksTUFBTSx3QkFBd0IsSUFBSSxzQ0FBc0MsS0FBSyxNQUFNLGNBQWM7QUFBQSxVQUM3RztBQUNBLGlCQUFPLFdBQVUsMEJBQTBCLE1BQU0sR0FBRyxJQUFJO0FBQUEsUUFDMUQ7QUFBQTtBQUFBO0FBQUE7QUFBQSxRQUtBLE9BQU8sMEJBQTBCLE1BQXlCLE9BQWUsS0FBcUI7QUFDNUYsY0FBSSxPQUFPO0FBQ1gsbUJBQVMsSUFBSSxPQUFPLElBQUksS0FBSyxLQUFLO0FBR2hDLGdCQUFJLEtBQUssQ0FBQyxJQUFJLEdBQUc7QUFDZixvQkFBTSxJQUFJO0FBQUE7QUFBQSxnQkFFUjtBQUFBLGNBQ0Y7QUFBQSxZQUNGO0FBQ0Esb0JBQVEsT0FBTyxLQUFLLENBQUMsQ0FBQztBQUFBLFVBQ3hCO0FBQ0EsaUJBQU87QUFBQSxRQUNUO0FBQUEsUUFFQSxPQUFPLGVBQWUsTUFBNEM7QUFDaEUsZ0JBQU0sT0FBTyxLQUFLO0FBQ2xCLGNBQUksU0FBUyxHQUFHO0FBQ2QsbUJBQU8sQ0FBQztBQUFBLFVBQ1YsV0FBVyxTQUFTLEdBQUc7QUFDckIsbUJBQU8sQ0FBQyxDQUFDO0FBQUEsVUFDWDtBQUNBLGdCQUFNLFVBQVUsSUFBSSxNQUFNLElBQUk7QUFDOUIsa0JBQVEsT0FBTyxDQUFDLElBQUk7QUFDcEIsa0JBQVEsT0FBTyxDQUFDLElBQUksS0FBSyxPQUFPLENBQUM7QUFDakMsbUJBQVMsSUFBSSxPQUFPLEdBQUcsS0FBSyxHQUFHLEVBQUUsR0FBRztBQUNsQyxvQkFBUSxDQUFDLElBQUksUUFBUSxJQUFJLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQztBQUFBLFVBQzFDO0FBQ0EsaUJBQU87QUFBQSxRQUNUO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFLQSxPQUFPLGNBQWMsTUFBYyxZQUE0QjtBQUM3RCxjQUFJLE9BQU8sQ0FBQyxjQUFjLFFBQVEsWUFBWTtBQUM1QyxrQkFBTSxJQUFJLE1BQU0sc0NBQXNDO0FBQUEsVUFDeEQ7QUFDQSxpQkFBTyxPQUFPLElBQUksT0FBTyxhQUFhO0FBQUEsUUFDeEM7QUFBQSxRQUVBLE9BQU8sY0FBYyxNQUF5QixZQUErQjtBQUMzRSxpQkFBTyxLQUFLLElBQUksQ0FBQyxNQUFNLEtBQUssY0FBYyxHQUFHLGNBQWMsS0FBSyxNQUFNLENBQUM7QUFBQSxRQUN6RTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBUUEsT0FBTyxnQkFBZ0IsR0FBc0IsTUFBNkM7QUFDeEYsY0FBSSxNQUFNO0FBQ1IsbUJBQU8sS0FBSyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztBQUFBLFVBQzdCLE9BQU87QUFDTCxtQkFBTyxFQUFFLE1BQU0sRUFBRSxRQUFRO0FBQUEsVUFDM0I7QUFBQSxRQUNGO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBT0EsT0FBTyxTQUFTLE1BQXlCQyxNQUEyQztBQUNsRixnQkFBTSxPQUFPLEtBQUs7QUFDbEIsaUJBQU8sS0FBSyxJQUFJLENBQUMsR0FBRyxNQUFNLElBQUlBLEtBQUksQ0FBQyxJQUFJQSxLQUFJLElBQUksSUFBSSxDQUFDO0FBQUEsUUFDdEQ7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFPQSxPQUFPLFNBQVMsUUFBMkIsUUFBb0M7QUFDN0UsY0FBSSxPQUFPLFdBQVcsT0FBTyxRQUFRO0FBQ25DLG1CQUFPO0FBQUEsVUFDVDtBQUNBLGlCQUFPLE9BQU8sTUFBTSxDQUFDLEdBQUcsTUFBTSxNQUFNLE9BQU8sQ0FBQyxDQUFDO0FBQUEsUUFDL0M7QUFBQSxNQUNGO0FBRU8sTUFBTSxlQUFOLE1BQU0sY0FBYTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBVXhCLE9BQU8scUJBQ0wsa0JBQ0EsV0FDQSxhQUNBLFNBQ0EsV0FDQSxNQUNNO0FBQ04sY0FBSSxDQUFDLG9CQUFvQixZQUFZLFdBQVcsVUFBVSxTQUFTLEdBQUc7QUFDcEUsa0JBQU0sSUFBSSxNQUFNLG9GQUFvRjtBQUFBLFVBQ3RHO0FBRUEsY0FBSSxrQkFBa0I7QUFFcEIscUJBQVMsTUFBTSxHQUFHLE1BQU0sVUFBVSxTQUFTLEdBQUcsT0FBTztBQUNuRCxrQkFBSSxPQUFPLFlBQVksUUFBUTtBQUM3Qiw0QkFBWSxLQUFLLFVBQVUsTUFBTSxDQUFDLENBQUM7QUFBQSxjQUNyQyxPQUFPO0FBQ0wsNEJBQVksR0FBRyxJQUFJLFVBQVUsTUFBTSxDQUFDO0FBQUEsY0FDdEM7QUFBQSxZQUNGO0FBQUEsVUFDRjtBQUdBLG1CQUFTLE1BQU0sR0FBRyxNQUFNLFlBQVksUUFBUSxPQUFPO0FBQ2pELGdCQUFJLE1BQU0sUUFBUSxRQUFRO0FBQ3hCLGtCQUFJLFFBQVEsR0FBRyxJQUFJLEdBQUc7QUFDcEIsc0JBQU0sSUFBSSxNQUFNLDhDQUE4QztBQUFBLGNBQ2hFO0FBQUEsWUFDRixPQUFPO0FBQ0wsc0JBQVEsS0FBSyxDQUFDO0FBQUEsWUFDaEI7QUFBQSxVQUNGO0FBR0EsbUJBQVMsTUFBTSxHQUFHLE1BQU0sWUFBWSxRQUFRLE9BQU87QUFDakQsZ0JBQUksTUFBTSxVQUFVLFFBQVE7QUFDMUIsa0JBQUksVUFBVSxHQUFHLElBQUksR0FBRztBQUN0QixzQkFBTSxJQUFJLE1BQU0sZ0RBQWdEO0FBQUEsY0FDbEU7QUFBQSxZQUNGLE9BQU87QUFDTCx3QkFBVSxLQUFLLENBQUM7QUFBQSxZQUNsQjtBQUFBLFVBQ0Y7QUFHQSxtQkFBUyxNQUFNLEdBQUcsTUFBTSxZQUFZLFNBQVMsR0FBRyxPQUFPO0FBQ3JELGdCQUFJLE1BQU0sS0FBSyxRQUFRO0FBQ3JCLGtCQUFJLEtBQUssR0FBRyxJQUFJLEdBQUc7QUFDakIsc0JBQU0sSUFBSSxNQUFNLDBDQUEwQztBQUFBLGNBQzVEO0FBQUEsWUFDRixPQUFPO0FBQ0wsbUJBQUssS0FBSyxDQUFDO0FBQUEsWUFDYjtBQUFBLFVBQ0Y7QUFHQSxtQkFBUyxNQUFNLEdBQUcsTUFBTSxZQUFZLFFBQVEsT0FBTztBQUNqRCxnQkFBSSxZQUFZLEdBQUcsS0FBSyxHQUFHO0FBQ3pCLG9CQUFNLElBQUksTUFBTSx5Q0FBeUM7QUFBQSxZQUMzRDtBQUVBLGdCQUFJLEtBQUssR0FBRyxLQUFLLFlBQVksR0FBRyxLQUFLLEtBQUssTUFBTSxZQUFZLE1BQU0sS0FBSyxZQUFZLEdBQUcsR0FBRztBQUN2RixvQkFBTSxJQUFJLE1BQU0sb0NBQW9DO0FBQUEsWUFDdEQ7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUFBO0FBQUEsUUFHQSxPQUFPLHlCQUNMLFdBQ0EsU0FDQSxXQUNBLGFBQ0EsTUFDQSxlQUNBLFNBQ007QUFDTixjQUFJLENBQUMsU0FBUztBQUNaO0FBQUEsVUFDRjtBQUVBLGNBQUksS0FBSyxXQUFXLEtBQUssVUFBVSxTQUFTLElBQUk7QUFDOUMsa0JBQU0sSUFBSSxNQUFNLDhEQUE4RDtBQUFBLFVBQ2hGO0FBRUEsY0FBSSxRQUFRLFdBQVcsVUFBVSxTQUFTLEdBQUc7QUFDM0Msa0JBQU0sSUFBSSxNQUFNLDJEQUEyRDtBQUFBLFVBQzdFO0FBRUEsY0FBSSxZQUFZLFdBQVcsVUFBVSxTQUFTLEdBQUc7QUFDL0Msa0JBQU0sSUFBSSxNQUFNLGlFQUFpRTtBQUFBLFVBQ25GO0FBRUEsbUJBQVMsTUFBTSxHQUFHLE1BQU0sVUFBVSxTQUFTLEdBQUcsT0FBTztBQUNuRCwwQkFBYTtBQUFBLGNBQ1gsVUFBVSxPQUFPLGdCQUFnQixJQUFJLEVBQUU7QUFBQSxjQUN2QyxRQUFRLEdBQUc7QUFBQSxjQUNYLFVBQVUsR0FBRztBQUFBLGNBQ2IsWUFBWSxHQUFHO0FBQUEsY0FDZjtBQUFBLGNBQ0E7QUFBQSxjQUNBLE1BQU0sVUFBVSxTQUFTO0FBQUEsY0FDekI7QUFBQSxZQUNGO0FBQUEsVUFDRjtBQUFBLFFBQ0Y7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFhQSxPQUFPLHVCQUNMLGtCQUNBLFdBQ0EsU0FDQSxXQUNBLGFBQ0EsTUFDQSxTQUNVO0FBQ1YsY0FBSSxVQUFVLFVBQVUsR0FBRztBQUN6QixrQkFBTSxJQUFJLE1BQU0sNENBQTRDO0FBQUEsVUFDOUQ7QUFHQSxnQkFBTSxhQUFhLENBQUMsVUFBVSxDQUFDLEdBQUcsVUFBVSxDQUFDLENBQUM7QUFFOUMsd0JBQWE7QUFBQSxZQUNYO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFVBQ0Y7QUFDQSxpQkFBTztBQUFBLFFBQ1Q7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBWUEsT0FBTyx1QkFDTCxXQUNBLFlBQ0EsU0FDQSxXQUNBLGFBQ0EsTUFDQSxTQUNVO0FBQ1YsY0FBSSxVQUFVLFVBQVUsS0FBSyxXQUFXLFVBQVUsR0FBRztBQUNuRCxrQkFBTSxJQUFJLE1BQU0seURBQXlEO0FBQUEsVUFDM0U7QUFHQSxnQkFBTSxhQUFhLENBQUMsVUFBVSxDQUFDLEdBQUcsV0FBVyxDQUFDLENBQUM7QUFFL0Msd0JBQWEsbUJBQW1CLE9BQU8sV0FBVyxZQUFZLFNBQVMsV0FBVyxhQUFhLE1BQU0sT0FBTztBQUM1RyxpQkFBTztBQUFBLFFBQ1Q7QUFBQTtBQUFBO0FBQUE7QUFBQSxRQUtBLE9BQWUsbUJBQ2Isa0JBQ0EsV0FDQSxZQUNBLFNBQ0EsV0FDQSxhQUNBLE1BQ0EsU0FDQTtBQUNBLGNBQUksa0JBQWtCO0FBQ3BCLHFCQUFTLE1BQU0sR0FBRyxNQUFNLFVBQVUsU0FBUyxHQUFHLE9BQU87QUFDbkQseUJBQVcsS0FBSyxDQUFDO0FBQUEsWUFDbkI7QUFBQSxVQUNGLE9BQU87QUFDTCxxQkFBUyxNQUFNLEdBQUcsTUFBTSxVQUFVLFNBQVMsR0FBRyxPQUFPO0FBQ25ELHlCQUFXO0FBQUEsZ0JBQ1QsY0FBYTtBQUFBLGtCQUNYLFVBQVUsTUFBTSxDQUFDO0FBQUEsa0JBQ2pCLFFBQVEsR0FBRztBQUFBLGtCQUNYLFVBQVUsR0FBRztBQUFBLGtCQUNiLFlBQVksR0FBRztBQUFBLGtCQUNmO0FBQUEsa0JBQ0E7QUFBQSxrQkFDQSxNQUFNLFVBQVUsU0FBUztBQUFBLGtCQUN6QjtBQUFBLGdCQUNGO0FBQUEsY0FDRjtBQUFBLFlBQ0Y7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUFBO0FBQUE7QUFBQSxRQUlBLE9BQWUsd0JBQ2IsUUFDQSxRQUNBLFVBQ0EsUUFDQSxNQUNBLGNBQ0EsY0FDQSxTQUNRO0FBQ1IsZ0JBQU0sVUFBVSxZQUFZLFNBQVMsS0FBSztBQUMxQyxjQUFJLFdBQVcsWUFBWSxVQUFVO0FBQ25DLG9CQUFRLFNBQVM7QUFBQSxjQUNmLEtBQUs7QUFDSCxxQkFBSyxZQUFZLElBQUk7QUFDckIscUJBQUssWUFBWSxJQUFJO0FBQ3JCLHVCQUFPLEtBQUssT0FBTyxTQUFTLFdBQVcsU0FBUyxDQUFDO0FBQUEsY0FDbkQsS0FBSztBQUFBLGNBQ0wsS0FBSztBQUNILG9CQUFJLGFBQWEsR0FBRztBQUNsQix3QkFBTSxJQUFJLE1BQU0scURBQXFEO0FBQUEsZ0JBQ3ZFLE9BQU87QUFDTCx3QkFBTSxvQkFBb0IsU0FBUyxTQUFTLEtBQUs7QUFDakQsd0JBQU0sYUFBYSxtQkFBbUIsS0FBSyxTQUFTLFNBQVM7QUFDN0QsdUJBQUssWUFBWSxJQUFJLFlBQVksZUFBZSxLQUFLLE9BQU8sWUFBWSxLQUFLLENBQUMsSUFBSSxLQUFLLE1BQU0sWUFBWSxDQUFDO0FBQzFHLHVCQUFLLFlBQVksSUFBSSxZQUFZLEtBQUssWUFBWTtBQUNsRCx5QkFBTyxLQUFLLE9BQU8sU0FBUyxZQUFZLFVBQVUsU0FBUyxDQUFDO0FBQUEsZ0JBQzlEO0FBQUEsY0FDRjtBQUNFLHNCQUFNLElBQUksTUFBTSwwQkFBMEI7QUFBQSxZQUM5QztBQUFBLFVBQ0YsT0FBTztBQUNMLG1CQUFPLEtBQUssT0FBTyxTQUFTLEtBQUssWUFBWSxJQUFJLEtBQUssWUFBWSxJQUFJLFdBQVcsU0FBUyxDQUFDO0FBQUEsVUFDN0Y7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sV0FBTixNQUFlO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFJcEIsT0FBTyxxQkFDTCxXQUNBLFdBQ0EsWUFDQSxZQUNBLFdBQ21CO0FBQ25CLGNBQUksVUFBVSxXQUFXLEtBQUssV0FBVyxXQUFXLEdBQUc7QUFDckQsa0JBQU0sSUFBSSxNQUFNLDRCQUE0QjtBQUFBLFVBQzlDO0FBRUEsY0FBSTtBQUNKLGNBQUk7QUFDSixjQUFJO0FBRUosY0FBSSxXQUFXO0FBQ2IsZ0JBQUksVUFBVSxDQUFDO0FBQ2YsZ0JBQUksVUFBVSxDQUFDO0FBQUEsVUFDakIsT0FBTztBQUNMLGdCQUFJLFVBQVUsQ0FBQztBQUNmLGdCQUFJLFVBQVUsQ0FBQztBQUFBLFVBQ2pCO0FBRUEsY0FBSSxPQUFPO0FBRVgsY0FBSSxZQUFZO0FBQ2QsZ0JBQUksV0FBVyxDQUFDO0FBQ2hCLG1CQUFPO0FBQUEsVUFDVCxPQUFPO0FBQ0wsZ0JBQUksV0FBVyxDQUFDO0FBQ2hCLG1CQUFPO0FBQUEsVUFDVDtBQUVBLGNBQUksV0FBVyxJQUFJLE1BQU0sR0FBRztBQUMxQixrQkFBTSxJQUFJLE1BQU0sb0JBQW9CO0FBQUEsVUFDdEM7QUFFQSxjQUFJLEtBQUssS0FBSyxLQUFLLEtBQUssS0FBSyxHQUFHO0FBQzlCLGtCQUFNLElBQUksTUFBTSx5QkFBeUI7QUFBQSxVQUMzQztBQUVBLGNBQUksYUFBYSxDQUFDLGNBQWMsaUJBQWlCLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHO0FBQ25FLGtCQUFNLElBQUksTUFBTSx3Q0FBd0M7QUFBQSxVQUMxRDtBQUVBLGlCQUFPLENBQUMsR0FBRyxHQUFHLENBQUM7QUFBQSxRQUNqQjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLFdBQVc7QUFDakIsTUFBTSxXQUFXO0FBQUE7QUFBQTs7O0FDN2lCeEIsTUFPYTtBQVBiO0FBQUE7QUFBQTtBQUtBO0FBRU8sTUFBTSxhQUFhLENBQ3hCLFlBQ0EsU0FXaUIsS0FBSyxrQ0FBa0MsSUFBSSxHQUFHLFVBQVU7QUFBQTtBQUFBOzs7QUNwQjNFLE1BZU0scUJBZU8sb0JBeURBLG9CQThGVCxZQUNFLG1CQU9BLHlCQVVBLHFCQVdBLGVBc0dBLGlCQXVJQSxtQkFrS087QUFqbUJiO0FBQUE7QUFBQTtBQUlBO0FBQ0E7QUFVQSxNQUFNLHNCQUFzQixvQkFBSSxJQUErQjtBQUFBLFFBQzdELENBQUMsV0FBVyxFQUFFO0FBQUEsUUFDZCxDQUFDLFdBQVcsRUFBRTtBQUFBLFFBQ2QsQ0FBQyxTQUFTLEVBQUU7QUFBQSxRQUNaLENBQUMsVUFBVSxFQUFFO0FBQUEsUUFDYixDQUFDLFNBQVMsRUFBRTtBQUFBLFFBQ1osQ0FBQyxVQUFVLEVBQUU7QUFBQSxRQUNiLENBQUMsUUFBUSxDQUFDO0FBQUEsUUFDVixDQUFDLFNBQVMsQ0FBQztBQUFBLFFBQ1gsQ0FBQyxRQUFRLENBQUM7QUFBQSxRQUNWLENBQUMsU0FBUyxDQUFDO0FBQUEsTUFDYixDQUFDO0FBSU0sTUFBTSxxQkFBcUIsQ0FBQyxNQUFrQixhQUE0QztBQUMvRixZQUFJLGFBQWEsU0FBUztBQUN4QixpQkFBTztBQUFBLFFBQ1Q7QUFFQSxjQUFNLGVBQWUsb0JBQW9CLElBQUksUUFBUTtBQUNyRCxZQUFJLENBQUMsY0FBYztBQUNqQixnQkFBTSxJQUFJLE1BQU0sNkNBQTZDLFFBQVEsRUFBRTtBQUFBLFFBQ3pFO0FBQ0EsY0FBTSxrQkFBa0IsZUFBZTtBQUV2QyxZQUFJLEtBQUssYUFBYSxvQkFBb0IsR0FBRztBQUMzQyxnQkFBTSxJQUFJLE1BQU0scURBQXFELGVBQWUsR0FBRztBQUFBLFFBQ3pGO0FBR0EsY0FBTSxjQUFjLEtBQUssYUFBYTtBQUN0QyxjQUFNLGdCQUFnQixLQUFLLGtDQUFrQyxRQUFRLEdBQUcsS0FBSyxRQUFRLEtBQUssWUFBWSxXQUFXO0FBRWpILGdCQUFRLFVBQVU7QUFBQSxVQUNoQixLQUFLO0FBQUEsVUFDTCxLQUFLLFVBQVU7QUFFYixrQkFBTSxhQUFhLElBQUksV0FBVyxXQUFXO0FBQzdDLHFCQUFTLElBQUksR0FBRyxJQUFJLGFBQWEsS0FBSztBQUNwQyxvQkFBTSxRQUFRLGNBQWMsQ0FBQztBQUc3QixrQkFBSSxRQUFRLGVBQWUsUUFBUSxDQUFDLGFBQWE7QUFDL0Msc0JBQU0sSUFBSSxNQUFNLDJEQUEyRDtBQUFBLGNBQzdFO0FBRUEseUJBQVcsQ0FBQyxJQUFJLE9BQU8sS0FBSztBQUFBLFlBQzlCO0FBRUEsbUJBQU8sSUFBSSxXQUFXLFdBQVcsTUFBTTtBQUFBLFVBQ3pDO0FBQUEsVUFDQSxLQUFLO0FBQUEsVUFDTCxLQUFLO0FBQUEsVUFDTCxLQUFLLFVBQVU7QUFFYixnQkFBSSxhQUFhLFVBQVU7QUFDekIsa0JBQUksY0FBYyxLQUFLLENBQUMsVUFBVSxRQUFRLFVBQVUsR0FBRztBQUNyRCxzQkFBTSxJQUFJLE1BQU0sNERBQTREO0FBQUEsY0FDOUU7QUFBQSxZQUNGO0FBRUEsa0JBQU0sYUFBYSxXQUFXLEtBQUssZUFBZSxNQUFNO0FBQ3hELG1CQUFPLElBQUksV0FBVyxXQUFXLE1BQU07QUFBQSxVQUN6QztBQUFBLFVBQ0E7QUFDRSxrQkFBTSxJQUFJLE1BQU0sb0NBQW9DLFFBQVEsYUFBYTtBQUFBLFFBQzdFO0FBQUEsTUFDRjtBQUlPLE1BQU0scUJBQXFCLENBQUMsTUFBa0IsYUFBNEM7QUFDL0YsWUFBSSxhQUFhLFNBQVM7QUFDeEIsaUJBQU87QUFBQSxRQUNUO0FBR0EsWUFBSSxLQUFLLGFBQWEsTUFBTSxHQUFHO0FBQzdCLGdCQUFNLElBQUksTUFBTSw4REFBOEQ7QUFBQSxRQUNoRjtBQUdBLGNBQU0sY0FBYyxLQUFLLGFBQWE7QUFDdEMsY0FBTSxhQUFhLElBQUksV0FBVyxLQUFLLFFBQVEsS0FBSyxZQUFZLFdBQVc7QUFFM0UsZ0JBQVEsVUFBVTtBQUFBLFVBQ2hCLEtBQUssU0FBUztBQUNaLGtCQUFNLGdCQUFnQixjQUFjLEtBQUssWUFBWSxNQUFNO0FBQzNELG1CQUFPLElBQUksV0FBVyxjQUFjLE1BQU07QUFBQSxVQUM1QztBQUFBLFVBQ0EsS0FBSyxVQUFVO0FBQ2IsZ0JBQUksV0FBVyxLQUFLLENBQUMsVUFBVSxRQUFRLENBQUMsR0FBRztBQUN6QyxvQkFBTSxJQUFJLE1BQU0sNkRBQTZEO0FBQUEsWUFDL0U7QUFDQSxrQkFBTSxpQkFBaUIsZUFBZSxLQUFLLFlBQVksTUFBTTtBQUM3RCxtQkFBTyxJQUFJLFdBQVcsZUFBZSxNQUFNO0FBQUEsVUFDN0M7QUFBQSxVQUNBLEtBQUssUUFBUTtBQUNYLGdCQUFJLFdBQVcsS0FBSyxDQUFDLFVBQVUsUUFBUSxRQUFRLFFBQVEsR0FBRyxHQUFHO0FBQzNELG9CQUFNLElBQUksTUFBTSwwREFBMEQ7QUFBQSxZQUM1RTtBQUNBLGtCQUFNLFlBQVksVUFBVSxLQUFLLFlBQVksTUFBTTtBQUNuRCxtQkFBTyxJQUFJLFdBQVcsVUFBVSxNQUFNO0FBQUEsVUFDeEM7QUFBQSxVQUNBLEtBQUssU0FBUztBQUNaLGdCQUFJLFdBQVcsS0FBSyxDQUFDLFVBQVUsUUFBUSxLQUFLLFFBQVEsR0FBRyxHQUFHO0FBQ3hELG9CQUFNLElBQUksTUFBTSwyREFBMkQ7QUFBQSxZQUM3RTtBQUNBLG1CQUFPLFdBQVcsS0FBSyxZQUFZLE1BQU07QUFBQSxVQUMzQztBQUFBLFVBQ0EsS0FBSyxVQUFVO0FBQ2IsZ0JBQUksV0FBVyxLQUFLLENBQUMsVUFBVSxRQUFRLENBQUMsR0FBRztBQUN6QyxvQkFBTSxJQUFJLE1BQU0sOERBQThEO0FBQUEsWUFDaEY7QUFDQSxrQkFBTSxjQUFjLFlBQVksS0FBSyxZQUFZLE1BQU07QUFDdkQsbUJBQU8sSUFBSSxXQUFXLFlBQVksTUFBTTtBQUFBLFVBQzFDO0FBQUEsVUFDQTtBQUNFLGtCQUFNLElBQUksTUFBTSwrQ0FBK0MsUUFBUSxFQUFFO0FBQUEsUUFDN0U7QUFBQSxNQUNGO0FBNkNBLE1BQUksYUFBYTtBQUNqQixNQUFNLG9CQUFvQixNQUFnQjtBQU8xQyxNQUFNLDBCQUEwQixvQkFBSSxJQUEwQztBQUFBLFFBQzVFLENBQUMsUUFBUSxPQUFPO0FBQUEsUUFDaEIsQ0FBQyxTQUFTLE9BQU87QUFBQSxRQUNqQixDQUFDLFVBQVUsT0FBTztBQUFBLFFBQ2xCLENBQUMsU0FBUyxPQUFPO0FBQUEsTUFDbkIsQ0FBQztBQUtELE1BQU0sc0JBQXNCLENBQUMsVUFBNkIsVUFBcUM7QUFDN0YsY0FBTSxlQUFlLG9CQUFvQixJQUFJLFFBQVE7QUFDckQsWUFBSSxDQUFDLGNBQWM7QUFDakIsZ0JBQU0sSUFBSSxNQUFNLDZDQUE2QyxRQUFRLEVBQUU7QUFBQSxRQUN6RTtBQUNBLGVBQU8sTUFBTSxTQUFTLElBQUksS0FBSyxLQUFNLE1BQU0sT0FBTyxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxlQUFnQixDQUFDLElBQUk7QUFBQSxNQUM1RjtBQUtBLE1BQU0sZ0JBQU4sTUFBb0I7QUFBQSxRQWFsQixZQUFZLFlBT1Q7QUFoQkg7QUFBQSxlQUFPLGtCQUFrQjtBQWlCdkIsZ0JBQU0sRUFBRSxXQUFXLFNBQVMsUUFBUSxVQUFVLE9BQU8saUJBQWlCLElBQUk7QUFDMUUsZUFBSyxZQUFZO0FBQ2pCLGVBQUssWUFBWTtBQUNqQixlQUFLLFdBQVc7QUFDaEIsZUFBSyxXQUFXO0FBQ2hCLGVBQUssY0FBYztBQUNuQixlQUFLLG1CQUFtQjtBQUFBLFFBQzFCO0FBQUEsUUFFQSxJQUFXLFNBQW1CO0FBQzVCLGlCQUFPLEtBQUs7QUFBQSxRQUNkO0FBQUEsUUFFQSxJQUFXLE9BQTBCO0FBQ25DLGlCQUFPLEtBQUs7QUFBQSxRQUNkO0FBQUEsUUFFQSxJQUFXLGVBQThDO0FBQ3ZELGlCQUFPLEtBQUs7QUFBQSxRQUNkO0FBQUEsUUFFQSxJQUFXLFFBQTJCO0FBQ3BDLGlCQUFPLEtBQUs7QUFBQSxRQUNkO0FBQUEsUUFFQSxJQUFXLGFBQXFCO0FBQzlCLGlCQUFPLG9CQUFvQixLQUFLLFVBQVUsS0FBSyxXQUFXO0FBQUEsUUFDNUQ7QUFBQSxRQUVPLFVBQWdCO0FBQ3JCLG9CQUFVLFdBQVcsTUFBTSwrQkFBK0I7QUFDMUQsZUFBSyxTQUFTLFFBQVE7QUFBQSxRQUN4QjtBQUFBLFFBRU8sTUFBTSxNQUF3QjtBQUNuQyxlQUFLLFVBQVUsWUFBWSxLQUFLLFVBQVUsSUFBSTtBQUFBLFFBQ2hEO0FBQUEsUUFJQSxNQUFhLEtBQUssV0FBNkU7QUFDN0YsY0FBSSxLQUFLLGtCQUFrQjtBQUV6QixrQkFBTSxPQUFPLE1BQU0sS0FBSyxVQUFVLFdBQVcsS0FBSyxRQUFRO0FBQzFELGtCQUFNLGVBQWUsbUJBQW1CLElBQUksV0FBVyxJQUFJLEdBQUcsS0FBSyxRQUFRO0FBRTNFLGdCQUFJLFdBQVc7QUFDYixvQkFBTSxlQUNKLHFCQUFxQixjQUNqQixJQUFJLFdBQVcsU0FBUyxJQUN4QixJQUFJLFdBQVcsVUFBVSxRQUFRLFVBQVUsWUFBWSxVQUFVLFVBQVU7QUFDakYsMkJBQWEsSUFBSSxZQUFZO0FBQzdCLHFCQUFPO0FBQUEsWUFDVCxPQUFPO0FBQ0wscUJBQU8sYUFBYTtBQUFBLFlBQ3RCO0FBQUEsVUFDRixPQUFPO0FBQ0wsbUJBQU8sWUFBWSxLQUFLLFVBQVUsV0FBVyxLQUFLLFVBQVUsU0FBUyxJQUFJLEtBQUssVUFBVSxXQUFXLEtBQUssUUFBUTtBQUFBLFVBQ2xIO0FBQUEsUUFDRjtBQUFBLFFBRU8sZUFBZSxTQUFvQixVQUE2QixPQUFtQztBQUN4RyxpQkFDRSxLQUFLLGNBQWMsV0FDbkIsS0FBSyxhQUFhLFlBQ2xCLEtBQUssWUFBWSxXQUFXLE1BQU0sVUFDbEMsS0FBSyxZQUFZLE1BQU0sQ0FBQyxHQUFHLE1BQU0sTUFBTSxNQUFNLENBQUMsQ0FBQztBQUFBLFFBRW5EO0FBQUEsUUFFTyxtQkFBbUIsYUFBNEI7QUFDcEQsZUFBSyxrQkFBa0I7QUFBQSxRQUN6QjtBQUFBLE1BQ0Y7QUFRQSxNQUFNLGtCQUFOLE1BQXNCO0FBQUEsUUFHcEIsWUFDVSxlQUNBLFNBQ1I7QUFGUTtBQUNBO0FBQUEsUUFDUDtBQUFBLFFBRUgsSUFBVyxnQkFBMkM7QUFDcEQsaUJBQU8sS0FBSztBQUFBLFFBQ2Q7QUFBQSxRQUVPLGdCQUFzQjtBQUMzQixjQUFJLEtBQUssZUFBZTtBQUN0QixpQkFBSyxjQUFjLGNBQWMsS0FBSyxhQUFhO0FBQ25ELGlCQUFLLFVBQVU7QUFBQSxVQUNqQjtBQUFBLFFBQ0Y7QUFBQSxRQUVBLE1BQWEsYUFDWCxXQUNBLFVBQ0EsT0FDQSxTQUNtQjtBQUNuQixnQkFBTSxVQUFVLEtBQUssY0FBYyxhQUFhLFNBQVM7QUFDekQsY0FBSTtBQUVKLGNBQUksQ0FBQyxRQUFRLGdCQUFnQixFQUFFLE1BQU0sVUFBVSxTQUFTLFFBQVEsR0FBRztBQUNqRSwrQkFBbUIsd0JBQXdCLElBQUksUUFBUTtBQUN2RCxnQkFBSSxDQUFDLG9CQUFvQixDQUFDLFFBQVEsZ0JBQWdCLEVBQUUsTUFBTSxVQUFVLFNBQVMsZ0JBQWdCLEdBQUc7QUFDOUYsb0JBQU0sSUFBSSxNQUFNLDZDQUE2QyxRQUFRLEVBQUU7QUFBQSxZQUN6RTtBQUNBO0FBQUEsY0FDRTtBQUFBLGNBQ0EsTUFBTSxnRUFBZ0UsUUFBUSxPQUFPLGdCQUFnQjtBQUFBLFlBQ3ZHO0FBQUEsVUFDRjtBQUVBLGNBQUksS0FBSyxTQUFTO0FBQ2hCLGdCQUFJLEtBQUssUUFBUSxlQUFlLFNBQVMsVUFBVSxLQUFLLEdBQUc7QUFDekQscUJBQU8sS0FBSyxRQUFRO0FBQUEsWUFDdEIsT0FBTztBQUNMLGtCQUFJLFNBQVM7QUFDWCxvQkFBSSxLQUFLLFFBQVEsZUFBZSxvQkFBb0IsVUFBVSxLQUFLLEdBQUc7QUFDcEUsd0JBQU0sSUFBSSxNQUFNLG9EQUFvRDtBQUFBLGdCQUN0RTtBQUNBLHFCQUFLLGVBQWUsSUFBSSxXQUFXLE1BQU0sS0FBSyxRQUFRLEtBQUssQ0FBQztBQUFBLGNBQzlEO0FBQ0EsbUJBQUssY0FBYyxjQUFjLEtBQUssT0FBTztBQUFBLFlBQy9DO0FBQUEsVUFDRjtBQUdBLGdCQUFNLFFBQVEsT0FBTyxpQkFBaUIsY0FBYyxTQUFZLGNBQWMsT0FBTyxjQUFjO0FBQ25HLGVBQUssVUFBVSxNQUFNLEtBQUssY0FBYztBQUFBLFlBQ3RDO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUVBLGNBQUksV0FBVyxLQUFLLGNBQWM7QUFHaEMsaUJBQUssUUFBUSxNQUFNLEtBQUssWUFBWTtBQUNwQyxpQkFBSyxlQUFlO0FBQUEsVUFDdEI7QUFFQSxpQkFBTyxLQUFLLFFBQVE7QUFBQSxRQUN0QjtBQUFBLFFBRU8sT0FBTyxNQUF3QjtBQUNwQyxjQUFJLFVBQVU7QUFDZCxjQUFJLEtBQUssU0FBUztBQUNoQixnQkFBSSxLQUFLLFFBQVEsY0FBYztBQUM3QixrQkFBSSxLQUFLLFFBQVEsaUJBQWlCLFNBQVM7QUFFekMsMEJBQVUsbUJBQW1CLE1BQU0sS0FBSyxRQUFRLElBQUk7QUFDcEQscUJBQUssUUFBUSxtQkFBbUIsSUFBSTtBQUFBLGNBQ3RDLE9BQU87QUFDTCxzQkFBTSxJQUFJLE1BQU0sbUNBQW1DLEtBQUssUUFBUSxZQUFZLEVBQUU7QUFBQSxjQUNoRjtBQUFBLFlBQ0Y7QUFHQSxnQkFBSSxLQUFLLGVBQWUsS0FBSyxRQUFRLFlBQVk7QUFFL0MsbUJBQUssUUFBUSxNQUFNLE9BQU87QUFDMUI7QUFBQSxZQUNGLE9BQU87QUFDTCx3QkFBVSxXQUFXLE1BQU0seURBQXlEO0FBQ3BGLG1CQUFLLGNBQWM7QUFBQSxZQUNyQjtBQUFBLFVBQ0Y7QUFFQSxjQUFJLEtBQUssY0FBYztBQUNyQixpQkFBSyxhQUFhLElBQUksT0FBTztBQUFBLFVBQy9CLE9BQU87QUFDTCxpQkFBSyxlQUFlLElBQUksV0FBVyxPQUFPO0FBQUEsVUFDNUM7QUFBQSxRQUNGO0FBQUEsUUFFQSxNQUFhLFNBQVMsV0FBNkU7QUFDakcsY0FBSSxLQUFLLGNBQWM7QUFFckIsa0JBQU0sVUFBVSxLQUFLLFNBQVMsa0JBQzFCLG1CQUFtQixLQUFLLGNBQWMsS0FBSyxTQUFTLElBQUksSUFDeEQsS0FBSztBQUVULGdCQUFJLFdBQVc7QUFDYixrQkFBSSxxQkFBcUIsYUFBYTtBQUNwQyxvQkFBSSxXQUFXLFNBQVMsRUFBRSxJQUFJLE9BQU87QUFBQSxjQUN2QyxPQUFPO0FBQ0wsb0JBQUksV0FBVyxVQUFVLFFBQVEsVUFBVSxZQUFZLFVBQVUsVUFBVSxFQUFFLElBQUksT0FBTztBQUFBLGNBQzFGO0FBQ0E7QUFBQSxZQUNGLE9BQU87QUFDTCxxQkFBTyxRQUFRO0FBQUEsWUFDakI7QUFBQSxVQUNGO0FBQ0EsY0FBSSxDQUFDLEtBQUssU0FBUztBQUNqQixrQkFBTSxJQUFJLE1BQU0sOEJBQThCO0FBQUEsVUFDaEQ7QUFFQSxjQUFJLENBQUMsV0FBVztBQUNkLG1CQUFPLEtBQUssUUFBUSxLQUFLO0FBQUEsVUFDM0I7QUFDQSxpQkFBTyxLQUFLLFFBQVEsS0FBSyxTQUFTO0FBQUEsUUFDcEM7QUFBQSxNQUNGO0FBRUEsTUFBTSxvQkFBTixNQUFpRDtBQUFBLFFBSy9DLFlBQW9CLFNBQXVCO0FBQXZCO0FBSnBCLGVBQVEscUJBQXFELG9CQUFJLElBQUk7QUFDckUsZUFBUSxjQUErQixDQUFDO0FBQ3hDLGVBQVEsa0JBQXNDLG9CQUFJLElBQUk7QUFBQSxRQUVWO0FBQUEsUUFFckMsYUFBYSxXQUE4QjtBQUNoRCxnQkFBTSxVQUFVLEtBQUssUUFBUSxhQUFhLFNBQVM7QUFDbkQsY0FBSSxDQUFDLFNBQVM7QUFDWixrQkFBTSxJQUFJLE1BQU0sa0NBQWtDO0FBQUEsVUFDcEQ7QUFDQSxpQkFBTztBQUFBLFFBQ1Q7QUFBQSxRQUVPLGtCQUE0QjtBQUNqQyxnQkFBTSxXQUFXLGtCQUFrQjtBQUNuQyxlQUFLLG1CQUFtQixJQUFJLFVBQVUsSUFBSSxnQkFBZ0IsSUFBSSxDQUFDO0FBQy9ELGlCQUFPO0FBQUEsUUFDVDtBQUFBLFFBRU8sZ0JBQWdCLFVBQTBCO0FBQy9DLGdCQUFNLGdCQUFnQixLQUFLLG1CQUFtQixJQUFJLFFBQVE7QUFDMUQsY0FBSSxDQUFDLGVBQWU7QUFDbEI7QUFBQSxVQUNGO0FBQ0EsZUFBSyxtQkFBbUIsT0FBTyxRQUFRO0FBQ3ZDLGNBQUksY0FBYyxlQUFlO0FBQy9CLGlCQUFLLGNBQWMsY0FBYyxhQUFhO0FBQUEsVUFDaEQ7QUFBQSxRQUNGO0FBQUEsUUFFQSxNQUFhLGFBQ1gsV0FDQSxVQUNBLFVBQ0EsT0FDQSxTQUNtQjtBQUNuQjtBQUFBLFlBQ0U7QUFBQSxZQUNBLE1BQ0UsaURBQWlELFFBQVEsZUFDdkQsUUFDRixZQUFZLEtBQUssY0FBYyxPQUFPO0FBQUEsVUFDMUM7QUFDQSxnQkFBTSxTQUFTLEtBQUssbUJBQW1CLElBQUksUUFBUTtBQUNuRCxjQUFJLENBQUMsUUFBUTtBQUNYLGtCQUFNLElBQUksTUFBTSxtQkFBbUI7QUFBQSxVQUNyQztBQUNBLGlCQUFPLE9BQU8sYUFBYSxXQUFXLFVBQVUsT0FBTyxPQUFPO0FBQUEsUUFDaEU7QUFBQSxRQUVPLE9BQU8sVUFBb0IsTUFBd0I7QUFDeEQsZ0JBQU0sU0FBUyxLQUFLLG1CQUFtQixJQUFJLFFBQVE7QUFDbkQsY0FBSSxDQUFDLFFBQVE7QUFDWCxrQkFBTSxJQUFJLE1BQU0sbUJBQW1CO0FBQUEsVUFDckM7QUFDQSxpQkFBTyxPQUFPLElBQUk7QUFBQSxRQUNwQjtBQUFBLFFBSUEsTUFBTSxTQUFTLFVBQW9CLFdBQTZFO0FBQzlHO0FBQUEsWUFDRTtBQUFBLFlBQ0EsTUFBTSw2Q0FBNkMsUUFBUSxnQkFBZ0IsV0FBVyxVQUFVO0FBQUEsVUFDbEc7QUFDQSxnQkFBTSxnQkFBZ0IsS0FBSyxtQkFBbUIsSUFBSSxRQUFRO0FBQzFELGNBQUksQ0FBQyxlQUFlO0FBQ2xCLGtCQUFNLElBQUksTUFBTSxtQkFBbUI7QUFBQSxVQUNyQztBQUNBLGlCQUFPLGNBQWMsU0FBUyxTQUFTO0FBQUEsUUFDekM7QUFBQSxRQUVPLHlCQUF5QixXQUF5QjtBQUN2RCxxQkFBVyxVQUFVLEtBQUssYUFBYTtBQUNyQyxnQkFBSSxPQUFPLGNBQWMsV0FBVztBQUNsQyxxQkFBTyxRQUFRO0FBQUEsWUFDakI7QUFBQSxVQUNGO0FBQ0EsZUFBSyxjQUFjLEtBQUssWUFBWSxPQUFPLENBQUMsV0FBVyxPQUFPLGNBQWMsU0FBUztBQUFBLFFBQ3ZGO0FBQUEsUUFFTyxlQUNMLFdBQ0EsVUFDQSxVQUNBLE9BQ1U7QUFDVixnQkFBTSxVQUFVLEtBQUssYUFBYSxTQUFTO0FBQzNDLGdCQUFNLFdBQVcsa0JBQWtCO0FBR25DLGdCQUFNLFVBQVUsSUFBSSxjQUFjO0FBQUEsWUFDaEM7QUFBQSxZQUNBO0FBQUEsWUFDQSxRQUFRO0FBQUEsWUFDUjtBQUFBLFlBQ0E7QUFBQSxVQUNGLENBQUM7QUFDRCxlQUFLLG1CQUFtQixJQUFJLFVBQVUsSUFBSSxnQkFBZ0IsTUFBTSxPQUFPLENBQUM7QUFDeEUsZUFBSyxnQkFBZ0IsSUFBSSxPQUFPO0FBQ2hDLGlCQUFPO0FBQUEsUUFDVDtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBS0EsTUFBYSxnQkFDWCxXQUNBLFVBQ0EsT0FDQSxPQUNBLFVBQ0EsVUFDQSxrQkFDd0I7QUFDeEIsZ0JBQU0sVUFBVSxLQUFLLGFBQWEsU0FBUztBQUMzQyxxQkFBVyxDQUFDLE9BQU9DLE9BQU0sS0FBSyxLQUFLLFlBQVksUUFBUSxHQUFHO0FBQ3hELGdCQUFJQSxRQUFPLGVBQWUsU0FBUyxVQUFVLEtBQUssR0FBRztBQUNuRDtBQUFBLGdCQUNFO0FBQUEsZ0JBQ0EsTUFDRSxxQ0FBcUMsUUFBUSxLQUMzQyxtQkFBbUIscUJBQXFCLGdCQUFnQixNQUFNLEVBQ2hFLFdBQVcsS0FBSztBQUFBLGNBQ3BCO0FBQ0Esb0JBQU0sVUFBVSxLQUFLLFlBQVksT0FBTyxPQUFPLENBQUMsRUFBRSxDQUFDO0FBQ25ELHNCQUFRLFlBQVk7QUFDcEIscUJBQU87QUFBQSxZQUNUO0FBQUEsVUFDRjtBQUNBO0FBQUEsWUFDRTtBQUFBLFlBQ0EsTUFDRSw2Q0FBNkMsUUFBUSxLQUNuRCxtQkFBbUIscUJBQXFCLGdCQUFnQixNQUFNLEVBQ2hFLFdBQVcsS0FBSztBQUFBLFVBQ3BCO0FBQ0EsZ0JBQU0sU0FBUyxNQUFNLFFBQVEsYUFBYTtBQUFBLFlBQ3hDLFVBQVUsb0JBQW9CO0FBQUE7QUFBQSxZQUM5QjtBQUFBLFlBQ0EsWUFBWTtBQUFBLFlBQ1o7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFVBQ0YsQ0FBQztBQUNELGlCQUFPLElBQUksY0FBYyxFQUFFLFdBQVcsU0FBUyxRQUFRLFVBQVUsT0FBTyxpQkFBaUIsQ0FBQztBQUFBLFFBQzVGO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFLTyxjQUFjLGVBQThCO0FBQ2pELGNBQUksS0FBSyxnQkFBZ0IsSUFBSSxhQUFhLEdBQUc7QUFDM0MsaUJBQUssZ0JBQWdCLE9BQU8sYUFBYTtBQUFBLFVBQzNDO0FBQ0EsZUFBSyxZQUFZLEtBQUssYUFBYTtBQUFBLFFBQ3JDO0FBQUEsTUFDRjtBQUVPLE1BQU0sc0JBQXNCLElBQUksU0FDckMsSUFBSSxrQkFBa0IsR0FBRyxJQUFJO0FBQUE7QUFBQTs7O0FDbG1CL0IsTUFvQk0sNkJBb0JBLHlCQWdCTztBQXhEYjtBQUFBO0FBQUE7QUFVQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBS0EsTUFBTSw4QkFBOEIsb0JBQUksSUFBaUM7QUFBQSxRQUN2RSxnQkFBaUIsU0FBUztBQUFBLFFBQzFCLG1CQUFtQixTQUFTO0FBQUEsUUFDNUIsZ0JBQWlCLE9BQU87QUFBQSxRQUN4QixrQkFBa0IsUUFBUTtBQUFBLFFBQzFCLGdCQUFpQixPQUFPO0FBQUEsUUFDeEIsa0JBQWtCLFFBQVE7QUFBQSxRQUMxQixnQkFBZ0IsTUFBTTtBQUFBLFFBQ3RCLGlCQUFpQixPQUFPO0FBQUEsUUFDeEIsZUFBZ0IsTUFBTTtBQUFBLFFBQ3RCLGdCQUFpQixPQUFPO0FBQUEsUUFDeEIsZUFBZ0IsT0FBTztBQUFBLE1BQ3pCLENBQUM7QUFRRCxNQUFNLDBCQUEwQixDQUFDLEdBQXNCLE1BQWtDO0FBQ3ZGLFlBQUksTUFBTSxHQUFHO0FBQ1gsaUJBQU87QUFBQSxRQUNUO0FBQ0EsWUFBSSxNQUFNLFVBQWEsTUFBTSxRQUFXO0FBQ3RDLGlCQUFPO0FBQUEsUUFDVDtBQUNBLGNBQU0sUUFBUSxPQUFPLEtBQUssQ0FBQyxFQUFFLEtBQUs7QUFDbEMsY0FBTSxRQUFRLE9BQU8sS0FBSyxDQUFDLEVBQUUsS0FBSztBQUNsQyxlQUFPLE1BQU0sV0FBVyxNQUFNLFVBQVUsTUFBTSxNQUFNLENBQUMsS0FBSyxVQUFVLFFBQVEsTUFBTSxLQUFLLEtBQUssRUFBRSxHQUFHLE1BQU0sRUFBRSxHQUFHLENBQUM7QUFBQSxNQUMvRztBQU1PLE1BQU0sZUFBTixNQUFtQjtBQUFBLFFBNEN4QixZQUFZQyxNQUFVO0FBeEN0QjtBQUFBO0FBQUE7QUFBQSxlQUFRLGdCQUFnQixvQkFBb0IsSUFBSTtBQUloRDtBQUFBO0FBQUE7QUFBQSxlQUFRLHVCQUF1QixvQkFBSSxJQUF1QjtBQUkxRDtBQUFBO0FBQUE7QUFBQSxlQUFRLHdCQUF3QixvQkFBSSxJQUE0QjtBQUloRTtBQUFBO0FBQUE7QUFBQSxlQUFRLGlCQUFtQyxDQUFDO0FBUTVDO0FBQUE7QUFBQTtBQUFBLGVBQVEscUJBQTRDLG9CQUFJLElBQUk7QUFJNUQ7QUFBQTtBQUFBO0FBQUEsZUFBUSxzQkFBNkMsb0JBQUksSUFBSTtBQUs3RDtBQUFBO0FBQUE7QUFBQTtBQUFBLGVBQVEsdUJBQWlDLENBQUM7QUFLMUM7QUFBQTtBQUFBO0FBQUE7QUFBQSxlQUFRLHdCQUFrQyxDQUFDO0FBSTNDO0FBQUE7QUFBQTtBQUFBLGVBQVEsNEJBQXFELG9CQUFJLElBQUk7QUFHbkUsMEJBQWdCQSxLQUFJLFVBQVcsQ0FBQyxDQUFDQSxLQUFJLEtBQUs7QUFBQSxRQUM1QztBQUFBLFFBRUEsSUFBVyxtQkFBMkI7QUFDcEMsY0FBSSxLQUFLLG9CQUFvQixRQUFXO0FBQ3RDLGtCQUFNLElBQUksTUFBTSxtQkFBbUI7QUFBQSxVQUNyQztBQUNBLGlCQUFPLEtBQUs7QUFBQSxRQUNkO0FBQUEsUUFFTyxXQUFXLFdBQXlCO0FBQ3pDLG9CQUFVLFdBQVcsTUFBTSxrQ0FBa0MsU0FBUyxHQUFHO0FBQ3pFLGVBQUssa0JBQWtCO0FBQUEsUUFDekI7QUFBQSxRQUVPLFNBQVMsV0FBeUI7QUFDdkMsb0JBQVUsV0FBVyxNQUFNLGdDQUFnQyxTQUFTLEdBQUc7QUFDdkUsZ0JBQU0sWUFBWSxLQUFLLDBCQUEwQixJQUFJLFNBQVM7QUFDOUQsY0FBSSxDQUFDLFdBQVc7QUFDZDtBQUFBLFVBQ0Y7QUFDQSxxQkFBVyxZQUFZLFdBQVc7QUFDaEMsc0JBQVUsV0FBVyxNQUFNLGlEQUFpRCxRQUFRLEdBQUc7QUFDdkYsaUJBQUssY0FBYyxnQkFBZ0IsUUFBUTtBQUFBLFVBQzdDO0FBQ0EsZUFBSywwQkFBMEIsT0FBTyxTQUFTO0FBQy9DLGVBQUssa0JBQWtCO0FBQUEsUUFDekI7QUFBQSxRQUVBLE1BQWEsZ0JBQWdCLGlCQUFvRTtBQUMvRixjQUFJLDJCQUEyQixXQUFXO0FBQ3hDLGtCQUFNQyxrQkFBaUIsS0FBSyxlQUFlLFVBQVUsQ0FBQyxVQUFVLE1BQU0sY0FBYyxlQUFlO0FBQ25HLGdCQUFJQSxvQkFBbUIsSUFBSTtBQUN6QixxQkFBTyxLQUFLLGVBQWVBLGVBQWMsRUFBRTtBQUFBLFlBQzdDLE9BQU87QUFDTCxvQkFBTSxZQUFZLE1BQU0sVUFBVSxHQUFHLGNBQWMsZUFBZTtBQUNsRSxtQkFBSyxlQUFlLEtBQUssRUFBRSxXQUFXLGlCQUFpQixVQUFVLENBQUM7QUFDbEUscUJBQU87QUFBQSxZQUNUO0FBQUEsVUFDRixXQUFXLG9CQUFvQixRQUFXO0FBQ3hDLGtCQUFNQSxrQkFBaUIsS0FBSyxlQUFlO0FBQUEsY0FDekMsQ0FBQyxVQUFVLE1BQU0sWUFBWSxVQUFhLE1BQU0sY0FBYztBQUFBLFlBQ2hFO0FBQ0EsZ0JBQUlBLG9CQUFtQixJQUFJO0FBQ3pCLHFCQUFPLEtBQUssZUFBZUEsZUFBYyxFQUFFO0FBQUEsWUFDN0MsT0FBTztBQUNMLG9CQUFNLFlBQVksTUFBTSxVQUFVLEdBQUcsY0FBYztBQUNuRCxtQkFBSyxlQUFlLEtBQUssRUFBRSxVQUFVLENBQUM7QUFDdEMscUJBQU87QUFBQSxZQUNUO0FBQUEsVUFDRjtBQUVBLGdCQUFNLGlCQUFpQixLQUFLLGVBQWU7QUFBQSxZQUFVLENBQUMsVUFDcEQsd0JBQXdCLE1BQU0sU0FBUyxlQUFlO0FBQUEsVUFDeEQ7QUFDQSxjQUFJLG1CQUFtQixJQUFJO0FBQ3pCLG1CQUFPLEtBQUssZUFBZSxjQUFjLEVBQUU7QUFBQSxVQUM3QyxPQUFPO0FBQ0wsa0JBQU0sWUFBWSxNQUFNLFVBQVUsR0FBRyxjQUFjLGVBQWU7QUFDbEUsaUJBQUssZUFBZSxLQUFLLEVBQUUsU0FBUyxpQkFBaUIsVUFBVSxDQUFDO0FBQ2hFLG1CQUFPO0FBQUEsVUFDVDtBQUFBLFFBQ0Y7QUFBQSxRQUVPLGtCQUFrQixXQUFtQixXQUE0QjtBQUN0RSxlQUFLLHFCQUFxQixJQUFJLFdBQVcsU0FBUztBQUNsRCxjQUFJLGFBQWEsS0FBSyxzQkFBc0IsSUFBSSxTQUFTO0FBQ3pELGNBQUksQ0FBQyxZQUFZO0FBQ2YseUJBQWEsb0JBQUksSUFBSTtBQUNyQixpQkFBSyxzQkFBc0IsSUFBSSxXQUFXLFVBQVU7QUFBQSxVQUN0RDtBQUNBLHFCQUFXLElBQUksU0FBUztBQUV4QixjQUFJLEtBQUsscUJBQXFCLFNBQVMsR0FBRztBQUN4QyxpQkFBSyxtQkFBbUIsSUFBSSxXQUFXLEtBQUssb0JBQW9CO0FBQ2hFLGlCQUFLLHVCQUF1QixDQUFDO0FBQUEsVUFDL0I7QUFDQSxjQUFJLEtBQUssc0JBQXNCLFNBQVMsR0FBRztBQUN6QyxpQkFBSyxvQkFBb0IsSUFBSSxXQUFXLEtBQUsscUJBQXFCO0FBQ2xFLGlCQUFLLHdCQUF3QixDQUFDO0FBQUEsVUFDaEM7QUFBQSxRQUNGO0FBQUEsUUFFTyxpQkFBaUIsV0FBeUI7QUFDL0MsZUFBSyxtQkFBbUIsT0FBTyxTQUFTO0FBQ3hDLGVBQUssb0JBQW9CLE9BQU8sU0FBUztBQUN6QyxnQkFBTSxZQUFZLEtBQUsscUJBQXFCLElBQUksU0FBUztBQUN6RCxjQUFJLENBQUMsV0FBVztBQUVkO0FBQUEsVUFDRjtBQUNBLGVBQUssY0FBYyx5QkFBeUIsU0FBUztBQUNyRCxlQUFLLHFCQUFxQixPQUFPLFNBQVM7QUFDMUMsZ0JBQU0sYUFBYSxLQUFLLHNCQUFzQixJQUFJLFNBQVM7QUFDM0QscUJBQVcsT0FBTyxTQUFTO0FBQzNCLGNBQUksV0FBVyxTQUFTLEdBQUc7QUFDekIsaUJBQUssc0JBQXNCLE9BQU8sU0FBUztBQUMzQyxrQkFBTSxpQkFBaUIsS0FBSyxlQUFlLFVBQVUsQ0FBQyxVQUFVLE1BQU0sY0FBYyxTQUFTO0FBQzdGLGdCQUFJLG1CQUFtQixJQUFJO0FBQ3pCLG1CQUFLLGVBQWUsT0FBTyxnQkFBZ0IsQ0FBQztBQUFBLFlBQzlDO0FBQUEsVUFDRjtBQUFBLFFBQ0Y7QUFBQSxRQUVPLGFBQWEsV0FBMEM7QUFDNUQsaUJBQU8sS0FBSyxxQkFBcUIsSUFBSSxTQUFTO0FBQUEsUUFDaEQ7QUFBQSxRQUVPLGtCQUE0QjtBQUNqQyxpQkFBTyxLQUFLLGNBQWMsZ0JBQWdCO0FBQUEsUUFDNUM7QUFBQSxRQUVPLGdCQUFnQixVQUEwQjtBQUMvQyxvQkFBVSxXQUFXLE1BQU0sc0NBQXNDLFFBQVEsR0FBRztBQUM1RSxlQUFLLGNBQWMsZ0JBQWdCLFFBQVE7QUFBQSxRQUM3QztBQUFBLFFBRUEsTUFBYSxhQUNYLFdBQ0EsVUFDQSxjQUNBLFlBQ0EsU0FDbUI7QUFDbkIsZ0JBQU0sZ0JBQWdCLDRCQUE0QixJQUFJLFlBQVk7QUFDbEUsY0FBSSxDQUFDLGVBQWU7QUFDbEIsa0JBQU0sSUFBSSxNQUFNLCtCQUErQixZQUFZLEVBQUU7QUFBQSxVQUMvRDtBQUNBLGlCQUFPLEtBQUssY0FBYztBQUFBLFlBQ3hCLGFBQWEsS0FBSztBQUFBLFlBQ2xCO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUFBLFFBQ0Y7QUFBQSxRQUVBLE1BQWEsc0JBQ1gsV0FDQSxjQUNBLE9BQ21CO0FBQ25CLG9CQUFVLFdBQVcsTUFBTSxnREFBZ0QsWUFBWSxZQUFZLEtBQUssR0FBRztBQUMzRyxnQkFBTSxXQUFXLDRCQUE0QixJQUFJLFlBQVk7QUFDN0QsY0FBSSxDQUFDLFVBQVU7QUFDYixrQkFBTSxJQUFJLE1BQU0sK0JBQStCLFlBQVksRUFBRTtBQUFBLFVBQy9EO0FBQ0EsZ0JBQU0sV0FBVyxLQUFLLGNBQWMsZ0JBQWdCO0FBQ3BELGdCQUFNLEtBQUssY0FBYyxhQUFhLFdBQVcsVUFBVSxVQUFVLE9BQU8sS0FBSztBQUNqRixnQkFBTSxZQUFZLEtBQUssMEJBQTBCLElBQUksU0FBUztBQUM5RCxjQUFJLENBQUMsV0FBVztBQUNkLGlCQUFLLDBCQUEwQixJQUFJLFdBQVcsQ0FBQyxRQUFRLENBQUM7QUFBQSxVQUMxRCxPQUFPO0FBQ0wsc0JBQVUsS0FBSyxRQUFRO0FBQUEsVUFDekI7QUFDQSxpQkFBTztBQUFBLFFBQ1Q7QUFBQSxRQUVPLGFBQWEsVUFBb0IsTUFBd0I7QUFDOUQsZ0JBQU1DLFFBQU8sWUFBWTtBQUN6QixjQUFJLENBQUNBLE1BQUssMEJBQTBCO0FBQ2xDLGtCQUFNLElBQUksTUFBTSx3RUFBd0U7QUFBQSxVQUMxRjtBQUNBLG9CQUFVLFdBQVcsTUFBTSxtQ0FBbUMsUUFBUSxXQUFXLEtBQUssVUFBVSxHQUFHO0FBQ25HLGVBQUssY0FBYyxPQUFPLFVBQVUsSUFBSTtBQUFBLFFBQzFDO0FBQUEsUUFFQSxNQUFhLGVBQWUsVUFBb0IsV0FBOEQ7QUFDNUcsaUJBQU8sS0FBSyxjQUFjLFNBQVMsVUFBVSxTQUFTO0FBQUEsUUFDeEQ7QUFBQSxRQUVPLHlCQUF5QixVQUFvQixNQUFnRTtBQUNsSCxpQkFBTyxZQUFZO0FBQ2pCLGtCQUFNLE9BQU8sTUFBTSxLQUFLLGNBQWMsU0FBUyxRQUFRO0FBQ3ZELG1CQUFPLFdBQVcsTUFBTSxJQUFJO0FBQUEsVUFDOUI7QUFBQSxRQUNGO0FBQUEsUUFFTyxpQkFBaUIsV0FBbUIsUUFBa0IsY0FBd0IsWUFBZ0M7QUFDbkgsZ0JBQU0sZ0JBQWdCLDRCQUE0QixJQUFJLFlBQVk7QUFDbEUsY0FBSSxDQUFDLGVBQWU7QUFDbEIsa0JBQU0sSUFBSSxNQUFNLCtCQUErQixZQUFZLEVBQUU7QUFBQSxVQUMvRDtBQUVBLGdCQUFNLEtBQUssS0FBSyxjQUFjLGVBQWUsV0FBVyxRQUFRLGVBQWUsVUFBVTtBQUN6RjtBQUFBLFlBQ0U7QUFBQSxZQUNBLE1BQ0UscUNBQXFDLE1BQU0sZUFBZSxhQUFhLGlCQUNyRSxVQUNGLG1CQUFtQixFQUFFO0FBQUEsVUFDekI7QUFDQSxpQkFBTztBQUFBLFFBQ1Q7QUFBQTtBQUFBLFFBR08sbUJBQ0wsa0JBQ0EsWUFDQSxZQUNBLFNBQ0EsTUFDQSxjQUNBLDRCQUE0QixPQUNqQjtBQUVYLGNBQUksQ0FBQyxjQUFjO0FBQ2pCLGtCQUFNLElBQUksTUFBTSwyQ0FBMkM7QUFBQSxVQUM3RDtBQUVBLGNBQUksV0FBVztBQUNmLGNBQUksaUJBQWlCLFdBQVcsSUFBSSxHQUFHO0FBQ3JDLHVCQUFXLGlCQUFpQixVQUFVLENBQUM7QUFBQSxVQUN6QztBQUNBLGdCQUFNLFdBQVcsYUFBYSxJQUFJLFFBQVE7QUFDMUMsY0FBSSxDQUFDLFVBQVU7QUFDYixrQkFBTSxJQUFJLE1BQU0sa0JBQWtCLFFBQVEsZ0NBQWdDO0FBQUEsVUFDNUU7QUFFQSxjQUFJLGFBQWEsYUFBYSxTQUFTLFlBQVk7QUFDakQsa0JBQU0sSUFBSSxNQUFNLDJFQUEyRTtBQUFBLFVBQzdGO0FBRUEsZ0JBQU0sU0FBUyxTQUFTLE1BQU0sWUFBWSxhQUFhLFVBQVUsRUFBRTtBQUNuRSxjQUFJO0FBQ0osa0JBQVEsS0FBSyxVQUFVO0FBQUEsWUFDckIsS0FBSztBQUNILDJCQUFhLElBQUksYUFBYSxNQUFNO0FBQ3BDO0FBQUEsWUFDRixLQUFLO0FBQ0gsMkJBQ0UsT0FBTyxpQkFBaUIsZUFBZSxhQUFhLE9BQU8sSUFBSSxhQUFhLE1BQU0sSUFBSSxJQUFJLFlBQVksTUFBTTtBQUM5RztBQUFBLFlBQ0YsS0FBSztBQUNILDJCQUFhLElBQUksV0FBVyxNQUFNO0FBQ2xDO0FBQUEsWUFDRixLQUFLO0FBQ0gsMkJBQWEsSUFBSSxZQUFZLE1BQU07QUFDbkM7QUFBQSxZQUNGLEtBQUs7QUFDSCxrQkFBSSwyQkFBMkI7QUFFN0Isc0JBQU0sY0FBYyxtQkFBbUIsSUFBSSxXQUFXLE1BQU0sR0FBRyxPQUFPO0FBQ3RFLDZCQUFhLElBQUksV0FBVyxZQUFZLE1BQU07QUFDOUMscUJBQUssV0FBVztBQUFBLGNBQ2xCLE9BQU87QUFDTCw2QkFBYSxJQUFJLGNBQWMsTUFBTTtBQUFBLGNBQ3ZDO0FBQ0E7QUFBQSxZQUNGLEtBQUs7QUFDSCwyQkFBYSxJQUFJLGVBQWUsTUFBTTtBQUN0QztBQUFBLFlBQ0YsS0FBSztBQUNILDJCQUFhLElBQUksVUFBVSxNQUFNO0FBQ2pDO0FBQUEsWUFDRixLQUFLO0FBQUEsWUFDTCxLQUFLO0FBQUEsWUFDTCxLQUFLO0FBQ0gsMkJBQWEsSUFBSSxXQUFXLE1BQU07QUFDbEM7QUFBQSxZQUNGO0FBQ0Usb0JBQU0sSUFBSSxNQUFNLDBCQUEwQixLQUFLLFFBQVEsaURBQWlEO0FBQUEsVUFDNUc7QUFFQTtBQUFBLFlBQ0U7QUFBQSxZQUNBLE1BQ0UseUNBQXlDLEtBQUssUUFBUSxZQUFZLEtBQUssS0FBSyxNQUMxRSw0QkFBNEIseUVBQXlFLEVBQ3ZHO0FBQUEsVUFDSjtBQUVBLGlCQUFPLFFBQVEsU0FBUyxNQUFNLFVBQVU7QUFBQSxRQUMxQztBQUFBLFFBRU8sbUJBQW1CLFdBQXlCO0FBQ2pELGVBQUsscUJBQXFCLEtBQUssU0FBUztBQUFBLFFBQzFDO0FBQUEsUUFFTyxvQkFBb0IsWUFBMEI7QUFDbkQsZUFBSyxzQkFBc0IsS0FBSyxVQUFVO0FBQUEsUUFDNUM7QUFBQSxRQUVPLGFBQWEsV0FBbUIsV0FBNEI7QUFDakUsZ0JBQU0sYUFBYSxLQUFLLG1CQUFtQixJQUFJLFNBQVM7QUFDeEQsY0FBSSxDQUFDLFlBQVk7QUFDZixtQkFBTztBQUFBLFVBQ1Q7QUFDQSxpQkFBTyxXQUFXLFNBQVMsU0FBUztBQUFBLFFBQ3RDO0FBQUEsUUFFTyxjQUFjLFdBQW1CLFlBQTZCO0FBQ25FLGdCQUFNLGNBQWMsS0FBSyxvQkFBb0IsSUFBSSxTQUFTO0FBQzFELGNBQUksQ0FBQyxhQUFhO0FBQ2hCLG1CQUFPO0FBQUEsVUFDVDtBQUNBLGlCQUFPLFlBQVksU0FBUyxVQUFVO0FBQUEsUUFDeEM7QUFBQSxRQUVPLGdDQUFnQyxXQUFtQixNQUFtQixVQUFVLE1BQWU7QUFDcEcsZ0JBQU0sVUFBVSxLQUFLLHFCQUFxQixJQUFJLFNBQVM7QUFDdkQsZ0JBQU0sV0FBVyw0QkFBNEIsSUFBSSwyQkFBMkIsSUFBSSxDQUFDO0FBRWpGLGNBQUksT0FBTyxhQUFhLGFBQWE7QUFDbkMsbUJBQU87QUFBQSxVQUNUO0FBRUEsY0FBSSxTQUFTO0FBQ1gsbUJBQU8sQ0FBQyxDQUFDLFNBQVMsZ0JBQWdCLEVBQUUsTUFBTSxVQUFVLFNBQVMsUUFBUTtBQUFBLFVBQ3ZFLE9BQU87QUFDTCxtQkFBTyxDQUFDLENBQUMsU0FBUyxnQkFBZ0IsRUFBRSxPQUFPLFVBQVUsU0FBUyxRQUFRO0FBQUEsVUFDeEU7QUFBQSxRQUNGO0FBQUEsUUFFTyxRQUFjO0FBQUEsUUFFckI7QUFBQSxNQUNGO0FBQUE7QUFBQTs7O0FDbGFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7OztBQ0FBLE1BbUZNLGdCQStCQSxXQUtBLDBCQUtBLHNCQVdGLE1BQ0Usb0JBWU8saUJBeUNQLG9CQStTTztBQTVlYjtBQUFBO0FBQUE7QUFJQTtBQUVBO0FBNkVBLE1BQU0saUJBQXNDLG9CQUFJLElBQUk7QUFBQSxRQUNsRCxDQUFDLElBQUksR0FBRztBQUFBLFFBQ1IsQ0FBQyxLQUFLLEdBQUc7QUFBQSxRQUNULENBQUMsS0FBSyxHQUFHO0FBQUEsUUFDVCxDQUFDLEtBQUssR0FBRztBQUFBLFFBQ1QsQ0FBQyxNQUFNLEdBQUc7QUFBQSxRQUNWLENBQUMsTUFBTSxHQUFHO0FBQUEsUUFDVixDQUFDLE1BQU0sRUFBRTtBQUFBLFFBQ1QsQ0FBQyxPQUFPLEVBQUU7QUFBQSxRQUNWLENBQUMsT0FBTyxFQUFFO0FBQUEsUUFDVixDQUFDLE9BQU8sRUFBRTtBQUFBLFFBQ1YsQ0FBQyxRQUFRLEVBQUU7QUFBQSxRQUNYLENBQUMsUUFBUSxFQUFFO0FBQUEsUUFDWCxDQUFDLFFBQVEsRUFBRTtBQUFBLFFBQ1gsQ0FBQyxTQUFTLEVBQUU7QUFBQSxRQUNaLENBQUMsU0FBUyxFQUFFO0FBQUEsUUFDWixDQUFDLFNBQVMsRUFBRTtBQUFBLFFBQ1osQ0FBQyxTQUFTLEVBQUU7QUFBQSxRQUNaLENBQUMsVUFBVSxFQUFFO0FBQUEsUUFDYixDQUFDLFVBQVUsRUFBRTtBQUFBLFFBQ2IsQ0FBQyxVQUFVLEVBQUU7QUFBQSxRQUNiLENBQUMsVUFBVSxFQUFFO0FBQUEsUUFDYixDQUFDLFVBQVUsQ0FBQztBQUFBLFFBQ1osQ0FBQyxVQUFVLENBQUM7QUFBQTtBQUFBO0FBQUEsUUFHWixDQUFDLFVBQVUsQ0FBQztBQUFBLFFBQ1osQ0FBQyxXQUFXLENBQUM7QUFBQSxRQUNiLENBQUMsV0FBVyxDQUFDO0FBQUEsTUFDZixDQUFDO0FBRUQsTUFBTSxZQUFzQixDQUFDO0FBSzdCLE1BQU0sMkJBQTJCLENBQUMsU0FBaUIsS0FBSyxLQUFLLE9BQU8sSUFBSSxJQUFJLEVBQUUsSUFBSTtBQUtsRixNQUFNLHVCQUF1QixDQUFDLFNBQWlCO0FBQzdDLGlCQUFTLE1BQU0sR0FBRyxNQUFNLFVBQVUsUUFBUSxPQUFPO0FBQy9DLGdCQUFNLGdCQUFnQixVQUFVLEdBQUc7QUFDbkMsY0FBSSxRQUFRLGVBQWU7QUFDekIsbUJBQU87QUFBQSxVQUNUO0FBQUEsUUFDRjtBQUVBLGVBQU8sS0FBSyxLQUFLLE9BQU8sRUFBRSxJQUFJO0FBQUEsTUFDaEM7QUFFQSxNQUFJLE9BQU87QUFDWCxNQUFNLHFCQUFxQixNQUFNO0FBWTFCLE1BQU0sa0JBQWtCLE9BQzdCLFNBQ0EsV0FDQSxjQUNBLG9CQUN3QjtBQUN4QixjQUFNLGFBQWEseUJBQXlCLFlBQVk7QUFDeEQsY0FBTSxnQkFBZ0IsUUFBUSxPQUFPO0FBQUE7QUFBQSxVQUVuQyxFQUFFLE1BQU0sWUFBWSxPQUFPLGVBQWUsV0FBVyxlQUFlLFNBQVM7QUFBQSxRQUMvRTtBQUNBLFlBQUk7QUFDRixnQkFBTSxpQkFBaUIsUUFBUSxrQkFBa0I7QUFDakQsa0JBQVEsZUFBZTtBQUN2Qix5QkFBZTtBQUFBLFlBQ2I7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUNBLGtCQUFRLE1BQU07QUFFZCxnQkFBTSxjQUFjLFNBQVMsV0FBVyxJQUFJO0FBRTVDLGdCQUFNLGNBQWMsY0FBYyxlQUFlO0FBQ2pELGNBQUksaUJBQWlCO0FBRW5CLGtCQUFNLGVBQWUsZ0JBQWdCO0FBQ3JDLHlCQUFhLElBQUksSUFBSSxXQUFXLGFBQWEsR0FBRyxZQUFZLENBQUM7QUFDN0QsbUJBQU87QUFBQSxVQUNULE9BQU87QUFHTCxtQkFBTyxJQUFJLFdBQVcsWUFBWSxNQUFNLEdBQUcsWUFBWSxDQUFDO0FBQUEsVUFDMUQ7QUFBQSxRQUNGLFVBQUU7QUFDQSx3QkFBYyxRQUFRO0FBQUEsUUFDeEI7QUFBQSxNQUNGO0FBRUEsTUFBTSxxQkFBTixNQUFtRDtBQUFBLFFBbUJqRCxZQUFvQixTQUF3QjtBQUF4QjtBQUNsQixlQUFLLGVBQWUsb0JBQUksSUFBSTtBQUM1QixlQUFLLGNBQWMsb0JBQUksSUFBSTtBQUMzQixlQUFLLHFCQUFxQixvQkFBSSxJQUFJO0FBQ2xDLGVBQUssaUJBQWlCLENBQUM7QUFDdkIsZUFBSyx5QkFBeUIsb0JBQUksSUFBSTtBQUV0QyxxQkFBVyxDQUFDLEdBQUcsS0FBSyxnQkFBZ0I7QUFDbEMsc0JBQVUsS0FBSyxHQUFHO0FBQ2xCLGlCQUFLLFlBQVksSUFBSSxLQUFLLENBQUMsQ0FBQztBQUM1QixpQkFBSyxtQkFBbUIsSUFBSSxLQUFLLENBQUMsQ0FBQztBQUFBLFVBQ3JDO0FBRUEsZUFBSyxlQUFlO0FBQUEsUUFDdEI7QUFBQSxRQUVBLE9BQU8sSUFBZSxNQUF3QjtBQUM1QyxnQkFBTSxpQkFBaUIsS0FBSztBQUM1QixnQkFBTSxZQUFZLEtBQUs7QUFDdkIsZ0JBQU0sWUFBWSxLQUFLO0FBQ3ZCLGdCQUFNLE9BQU8seUJBQXlCLFNBQVM7QUFHL0MsZ0JBQU0sZUFBZSxLQUFLLGFBQWEsSUFBSSxFQUFFO0FBQzdDLGNBQUksQ0FBQyxjQUFjO0FBQ2pCLGtCQUFNLElBQUksTUFBTSx1Q0FBdUM7QUFBQSxVQUN6RDtBQUNBLGNBQUksT0FBTyxhQUFhLFlBQVksTUFBTSxXQUFXO0FBQ25ELGtCQUFNLElBQUksTUFBTSx5Q0FBeUMsYUFBYSxZQUFZLGVBQWUsU0FBUyxFQUFFO0FBQUEsVUFDOUc7QUFHQSxnQkFBTSx3QkFBd0IsS0FBSyxRQUFRLE9BQU87QUFBQTtBQUFBLFlBRWhELEVBQUUsa0JBQWtCLE1BQU0sTUFBTSxPQUFPLGVBQWUsWUFBWSxlQUFlLFNBQVM7QUFBQSxVQUM1RjtBQUdBLGdCQUFNLGNBQWMsc0JBQXNCLGVBQWU7QUFDekQsY0FBSSxXQUFXLFdBQVcsRUFBRSxJQUFJLElBQUksV0FBVyxnQkFBZ0IsV0FBVyxTQUFTLENBQUM7QUFDcEYsZ0NBQXNCLE1BQU07QUFHNUIsZ0JBQU0saUJBQWlCLEtBQUssUUFBUSxPQUFPLHFCQUFxQjtBQUNoRSx5QkFBZSxtQkFBbUIsdUJBQXVCLEdBQUcsYUFBYSxRQUFRLFFBQVEsR0FBRyxJQUFJO0FBQ2hHLGVBQUssUUFBUSxPQUFPLE1BQU0sT0FBTyxDQUFDLGVBQWUsT0FBTyxDQUFDLENBQUM7QUFDMUQsZ0NBQXNCLFFBQVE7QUFFOUIsb0JBQVUsV0FBVyxNQUFNLHFDQUFxQyxFQUFFLEdBQUc7QUFBQSxRQUN2RTtBQUFBLFFBRUEsT0FBTyxVQUFxQixlQUFnQztBQUUxRCxnQkFBTSxxQkFBcUIsS0FBSyxhQUFhLElBQUksUUFBUTtBQUN6RCxjQUFJLENBQUMsb0JBQW9CO0FBQ3ZCLGtCQUFNLElBQUksTUFBTSwyQ0FBMkM7QUFBQSxVQUM3RDtBQUVBLGdCQUFNLDBCQUEwQixLQUFLLGFBQWEsSUFBSSxhQUFhO0FBQ25FLGNBQUksQ0FBQyx5QkFBeUI7QUFDNUIsa0JBQU0sSUFBSSxNQUFNLGdEQUFnRDtBQUFBLFVBQ2xFO0FBQ0EsY0FBSSxtQkFBbUIsaUJBQWlCLHdCQUF3QixjQUFjO0FBQzVFLGtCQUFNLElBQUksTUFBTSxtREFBbUQ7QUFBQSxVQUNyRTtBQUVBLGdCQUFNLE9BQU8seUJBQXlCLG1CQUFtQixZQUFZO0FBR3JFLGdCQUFNLGlCQUFpQixLQUFLLFFBQVEsa0JBQWtCO0FBQ3RELGVBQUssUUFBUSxlQUFlO0FBQzVCLHlCQUFlO0FBQUEsWUFDYixtQkFBbUIsUUFBUTtBQUFBLFlBQzNCO0FBQUEsWUFDQSx3QkFBd0IsUUFBUTtBQUFBLFlBQ2hDO0FBQUEsWUFDQTtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQUEsUUFFQSx1QkFBdUIsUUFBbUIsY0FBc0IsVUFBMkM7QUFDekcsY0FBSTtBQUNKLGNBQUksVUFBVTtBQUNaLGlCQUFLLFNBQVMsQ0FBQztBQUNmLGdCQUFJLFdBQVcsU0FBUyxDQUFDLEdBQUc7QUFDMUI7QUFBQSxnQkFDRTtBQUFBLGdCQUNBLE1BQ0UsdURBQXVELFlBQVksV0FBVyxFQUFFO0FBQUEsY0FDcEY7QUFDQSxxQkFBTztBQUFBLFlBQ1QsV0FBVyxLQUFLLFFBQVEsb0JBQW9CLElBQUksS0FBSyxRQUFRLGdCQUFpQixHQUFHO0FBQy9FLG9CQUFNLElBQUksTUFBTTtBQUFBLHNEQUM4QjtBQUFBLFlBQ2hEO0FBQUEsVUFDRixPQUFPO0FBQ0wsaUJBQUssbUJBQW1CO0FBQUEsVUFDMUI7QUFFQSxlQUFLLGFBQWEsSUFBSSxJQUFJLEVBQUUsU0FBUyxFQUFFLElBQUksdUJBQTJCLE9BQU8sR0FBRyxhQUFhLENBQUM7QUFDOUY7QUFBQSxZQUNFO0FBQUEsWUFDQSxNQUFNLHVEQUF1RCxZQUFZLFdBQVcsRUFBRTtBQUFBLFVBQ3hGO0FBQ0EsaUJBQU87QUFBQSxRQUNUO0FBQUEsUUFFQSx5QkFBeUIsSUFBcUI7QUFDNUMsY0FBSSxPQUFPLFFBQVc7QUFDcEIsaUJBQUssYUFBYSxPQUFPLEVBQUU7QUFDM0Isc0JBQVUsV0FBVyxNQUFNLDREQUE0RCxFQUFFLEVBQUU7QUFBQSxVQUM3RjtBQUFBLFFBQ0Y7QUFBQTtBQUFBLFFBR0EsT0FBTyxNQUFjLFFBQVEsZUFBZSxVQUFVLGVBQWUsV0FBVyxlQUFlLFVBQW1CO0FBQ2hILGdCQUFNLGFBQWEscUJBQXFCLElBQUk7QUFFNUMsY0FBSTtBQUdKLGdCQUFNLGFBQWEsUUFBUSxlQUFlLGFBQWEsZUFBZTtBQUV0RSxnQkFBTSxhQUFhLFFBQVEsZUFBZSxhQUFhLGVBQWU7QUFDdEUsY0FBSSxhQUFhLFdBQVc7QUFDMUIsa0JBQU0sY0FBYyxZQUFZLEtBQUssY0FBYyxLQUFLO0FBQ3hELGtCQUFNLFVBQVUsWUFBWSxJQUFJLFVBQVU7QUFDMUMsZ0JBQUksQ0FBQyxTQUFTO0FBRVosMEJBQVksS0FBSyxRQUFRLE9BQU8sYUFBYSxFQUFFLE1BQU0sWUFBWSxNQUFNLENBQUM7QUFBQSxZQUMxRSxPQUFPO0FBQ0wsa0JBQUksUUFBUSxTQUFTLEdBQUc7QUFFdEIsNEJBQVksUUFBUSxJQUFJO0FBQUEsY0FDMUIsT0FBTztBQUVMLDRCQUFZLEtBQUssUUFBUSxPQUFPLGFBQWEsRUFBRSxNQUFNLFlBQVksTUFBTSxDQUFDO0FBQUEsY0FDMUU7QUFBQSxZQUNGO0FBQUEsVUFDRixPQUFPO0FBRUwsd0JBQVksS0FBSyxRQUFRLE9BQU8sYUFBYSxFQUFFLE1BQU0sWUFBWSxNQUFNLENBQUM7QUFBQSxVQUMxRTtBQUVBLGdCQUFNLFVBQVUsRUFBRSxJQUFJLG1CQUFtQixHQUFHLHVCQUEyQixRQUFRLFVBQVU7QUFDekYsZUFBSyxhQUFhLElBQUksUUFBUSxJQUFJLEVBQUUsU0FBUyxjQUFjLE9BQU8sSUFBSSxFQUFFLENBQUM7QUFFekUsb0JBQVUsV0FBVyxNQUFNLHVDQUF1QyxJQUFJLFdBQVcsUUFBUSxFQUFFLEVBQUU7QUFDN0YsaUJBQU87QUFBQSxRQUNUO0FBQUEsUUFFQSxJQUFJLElBQW9DO0FBQ3RDLGlCQUFPLEtBQUssYUFBYSxJQUFJLEVBQUUsR0FBRztBQUFBLFFBQ3BDO0FBQUEsUUFFQSxRQUFRLFNBQTRCO0FBQ2xDLGdCQUFNLEtBQUssT0FBTyxZQUFZLFdBQVcsT0FBTyxPQUFPLElBQUk7QUFDM0QsZ0JBQU0sYUFBYSxLQUFLLGFBQWEsSUFBSSxFQUFFO0FBQzNDLGNBQUksQ0FBQyxZQUFZO0FBQ2YsZ0JBQUksS0FBSyxhQUFhLFNBQVMsR0FBRztBQUVoQyxxQkFBTztBQUFBLFlBQ1QsT0FBTztBQUNMLG9CQUFNLElBQUksTUFBTSwrQkFBK0I7QUFBQSxZQUNqRDtBQUFBLFVBQ0Y7QUFFQSxvQkFBVSxXQUFXLE1BQU0sc0NBQXNDLEVBQUUsZ0JBQWdCLFdBQVcsUUFBUSxFQUFFLEVBQUU7QUFFMUcsZUFBSyxhQUFhLE9BQU8sRUFBRTtBQUMzQixlQUFLLGVBQWUsS0FBSyxXQUFXLFFBQVEsTUFBTTtBQUdsRCxpQkFBTyxXQUFXO0FBQUEsUUFDcEI7QUFBQSxRQUVBLE1BQU0sU0FBUyxJQUFlLGlCQUFrRDtBQUM5RSxnQkFBTSxhQUFhLEtBQUssYUFBYSxJQUFJLE9BQU8sRUFBRSxDQUFDO0FBQ25ELGNBQUksQ0FBQyxZQUFZO0FBQ2Ysa0JBQU0sSUFBSSxNQUFNLHFCQUFxQjtBQUFBLFVBQ3ZDO0FBQ0EsZ0JBQU0sZ0JBQWdCLEtBQUssU0FBUyxXQUFXLFFBQVEsUUFBUSxXQUFXLGNBQWMsZUFBZTtBQUFBLFFBQ3pHO0FBQUEsUUFFQSx3QkFBOEI7QUFDNUIsY0FBSSxLQUFLLGVBQWUsV0FBVyxHQUFHO0FBQ3BDO0FBQUEsVUFDRjtBQUVBLGNBQUksS0FBSyxRQUFRLGtCQUFrQixXQUFXO0FBQzVDLHVCQUFXLFVBQVUsS0FBSyxnQkFBZ0I7QUFDeEMsb0JBQU0sZ0JBQWdCLGVBQWUsSUFBSSxPQUFPLElBQUk7QUFHcEQsbUJBQUssT0FBTyxRQUFRLGVBQWUsYUFBYSxlQUFlLFNBQVM7QUFFdEUsc0JBQU0sV0FBVyxLQUFLLFlBQVksSUFBSSxPQUFPLElBQUksS0FBSyxDQUFDO0FBQ3ZELG9CQUFJLGtCQUFrQixVQUFhLFNBQVMsVUFBVSxlQUFlO0FBQ25FLHlCQUFPLFFBQVE7QUFBQSxnQkFDakIsT0FBTztBQUNMLDJCQUFTLEtBQUssTUFBTTtBQUFBLGdCQUN0QjtBQUFBLGNBRUYsWUFBWSxPQUFPLFFBQVEsZUFBZSxhQUFhLGVBQWUsU0FBUztBQUU3RSxzQkFBTSxXQUFXLEtBQUssbUJBQW1CLElBQUksT0FBTyxJQUFJLEtBQUssQ0FBQztBQUM5RCxvQkFBSSxrQkFBa0IsVUFBYSxTQUFTLFVBQVUsZUFBZTtBQUNuRSx5QkFBTyxRQUFRO0FBQUEsZ0JBQ2pCLE9BQU87QUFDTCwyQkFBUyxLQUFLLE1BQU07QUFBQSxnQkFDdEI7QUFBQSxjQUNGLE9BQU87QUFDTCx1QkFBTyxRQUFRO0FBQUEsY0FDakI7QUFBQSxZQUNGO0FBQ0EsaUJBQUssaUJBQWlCLENBQUM7QUFBQSxVQUN6QixPQUFPO0FBR0wsZ0JBQUksa0JBQWtCLEtBQUssdUJBQXVCLElBQUksS0FBSyxRQUFRLGdCQUFpQjtBQUNwRixnQkFBSSxDQUFDLGlCQUFpQjtBQUNwQixnQ0FBa0IsQ0FBQztBQUNuQixtQkFBSyx1QkFBdUIsSUFBSSxLQUFLLFFBQVEsa0JBQW1CLGVBQWU7QUFBQSxZQUNqRjtBQUNBLHVCQUFXLFVBQVUsS0FBSyxnQkFBZ0I7QUFDeEMsOEJBQWdCLEtBQUssTUFBTTtBQUFBLFlBQzdCO0FBQ0EsaUJBQUssaUJBQWlCLENBQUM7QUFBQSxVQUN6QjtBQUFBLFFBQ0Y7QUFBQSxRQUVBLFVBQVU7QUFDUixlQUFLLFlBQVksUUFBUSxDQUFDLFlBQVk7QUFDcEMsb0JBQVEsUUFBUSxDQUFDLFdBQVc7QUFDMUIscUJBQU8sUUFBUTtBQUFBLFlBQ2pCLENBQUM7QUFBQSxVQUNILENBQUM7QUFDRCxlQUFLLG1CQUFtQixRQUFRLENBQUMsWUFBWTtBQUMzQyxvQkFBUSxRQUFRLENBQUMsV0FBVztBQUMxQixxQkFBTyxRQUFRO0FBQUEsWUFDakIsQ0FBQztBQUFBLFVBQ0gsQ0FBQztBQUVELGVBQUssYUFBYSxRQUFRLENBQUMsWUFBWTtBQUNyQyxvQkFBUSxRQUFRLE9BQU8sUUFBUTtBQUFBLFVBQ2pDLENBQUM7QUFFRCxlQUFLLHVCQUF1QixRQUFRLENBQUMsWUFBWTtBQUMvQyxvQkFBUSxRQUFRLENBQUMsV0FBVztBQUMxQixxQkFBTyxRQUFRO0FBQUEsWUFDakIsQ0FBQztBQUFBLFVBQ0gsQ0FBQztBQUNELGVBQUssZUFBZSxvQkFBSSxJQUFJO0FBQzVCLGVBQUssY0FBYyxvQkFBSSxJQUFJO0FBQzNCLGVBQUsscUJBQXFCLG9CQUFJLElBQUk7QUFDbEMsZUFBSyx5QkFBeUIsb0JBQUksSUFBSTtBQUFBLFFBQ3hDO0FBQUEsUUFFQSxrQkFBa0I7QUFDaEIsZUFBSyxnQkFBZ0I7QUFBQSxRQUN2QjtBQUFBLFFBRUEsaUJBQWlCLFdBQW1CO0FBRWxDLGdCQUFNLGlCQUFpQixLQUFLLHVCQUF1QixJQUFJLFNBQVM7QUFDaEUsY0FBSSxnQkFBZ0I7QUFDbEIsMkJBQWUsUUFBUSxDQUFDLFdBQVc7QUFDakMscUJBQU8sUUFBUTtBQUFBLFlBQ2pCLENBQUM7QUFDRCxpQkFBSyx1QkFBdUIsT0FBTyxTQUFTO0FBQUEsVUFDOUM7QUFHQSxlQUFLLGdCQUFnQjtBQUNyQixjQUFJLEtBQUssaUJBQWlCLEdBQUc7QUFDM0Isc0JBQVUsV0FBVyxNQUFNLHVDQUF1QztBQUNsRSxpQkFBSyxhQUFhLFFBQVEsQ0FBQyxZQUFZO0FBQ3JDLHNCQUFRLFFBQVEsT0FBTyxRQUFRO0FBQUEsWUFDakMsQ0FBQztBQUNELGlCQUFLLGVBQWUsb0JBQUksSUFBSTtBQUFBLFVBQzlCO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLHVCQUF1QixJQUFJLFNBQ3RDLElBQUksbUJBQW1CLEdBQUcsSUFBSTtBQUFBO0FBQUE7OztBQzdlaEMsTUFHTSwyQkF3Qk87QUEzQmI7QUFBQTtBQUFBO0FBR0EsTUFBTSw0QkFBTixNQUFnQztBQUFBLFFBQzlCLFlBQVksV0FBb0M7QUFDOUMsaUJBQU8sT0FBTyxNQUFNLFNBQVM7QUFBQSxRQUMvQjtBQUFBLFFBR0EsSUFBVyxXQUFtQjtBQUM1QixjQUFJLENBQUMsS0FBSyxLQUFLO0FBQ2IsaUJBQUssTUFBTSxPQUFPLG9CQUFvQixJQUFJLEVBQ3ZDLEtBQUssRUFDTCxJQUFJLENBQUMsU0FBUyxHQUFJLEtBQWlDLElBQUksQ0FBQyxFQUFFLEVBQzFELEtBQUssR0FBRztBQUFBLFVBQ2I7QUFDQSxpQkFBTyxLQUFLO0FBQUEsUUFDZDtBQUFBLE1BQ0Y7QUFTTyxNQUFNLDhCQUE4QixDQUN6QyxjQUM4QixJQUFJLDBCQUEwQixTQUFTO0FBQUE7QUFBQTs7O0FDN0J2RSxNQWlCYSxnQkFzTVAsbUJBdUNPLDZCQUtBLDJCQUtBLDRCQWlCQSxrQkFpQkEsWUFjQSxXQWdCQSxXQW1CQSxjQW1DUCxxQkEwVU8sZUFnQkEsZ0JBZUEsc0JBZUEsa0JBbUZQLGtCQXdLTztBQWovQmI7QUFBQTtBQUFBO0FBR0E7QUFDQTtBQWFPLE1BQU0saUJBQWlCO0FBc005QixNQUFNLG9CQUFvQixDQUFDLE1BQWMsZUFBeUQ7QUFDaEcsWUFBSSxlQUFlLEdBQUc7QUFDcEIsZ0JBQU0sSUFBSSxNQUFNLG1EQUFtRDtBQUFBLFFBQ3JFO0FBR0EsZ0JBQVEsT0FBTyxJQUFJLEdBQUc7QUFBQSxVQUNwQjtBQUNFLG1CQUFPLGFBQWEsSUFBSSxNQUFNLFVBQVUsVUFBVTtBQUFBLFVBQ3BEO0FBQ0UsbUJBQU8sYUFBYSxJQUFJLE1BQU0sVUFBVSxVQUFVO0FBQUEsVUFDcEQ7QUFDRSxtQkFBTyxhQUFhLElBQUksTUFBTSxVQUFVLFVBQVU7QUFBQSxVQUNwRDtBQUNFLG1CQUFPLGFBQWEsSUFBSSxNQUFNLFVBQVUsVUFBVTtBQUFBLFVBQ3BEO0FBQ0UsZ0JBQUksYUFBYSxHQUFHO0FBQ2xCLG9CQUFNLElBQUksTUFBTSw0Q0FBNEM7QUFBQSxZQUM5RDtBQUNBLG1CQUFPLENBQUMsYUFBYSxLQUFLO0FBQUEsVUFDNUI7QUFDRSxnQkFBSSxhQUFhLEdBQUc7QUFDbEIsb0JBQU0sSUFBSSxNQUFNLDRDQUE0QztBQUFBLFlBQzlEO0FBQ0EsbUJBQU8sQ0FBQyxhQUFhLEtBQUs7QUFBQSxVQUM1QjtBQUNFLGdCQUFJLGVBQWUsR0FBRztBQUNwQixvQkFBTSxJQUFJLE1BQU0sbUJBQW1CO0FBQUEsWUFDckM7QUFDQSxtQkFBTyxDQUFDLE9BQU8sWUFBWTtBQUFBLFVBQzdCO0FBQ0UsbUJBQU87QUFBQSxVQUNUO0FBQ0UsbUJBQU87QUFBQSxVQUNUO0FBQ0Usa0JBQU0sSUFBSSxNQUFNLHNCQUFzQixJQUFJLEVBQUU7QUFBQSxRQUNoRDtBQUFBLE1BQ0Y7QUFFTyxNQUFNLDhCQUE4QixDQUFDLE1BQWdCLGFBQTRCLE1BQU07QUFDNUYsY0FBTSxhQUFhLGtCQUFrQixNQUFNLFVBQVU7QUFDckQsZUFBTyxPQUFPLGVBQWUsV0FBVyxhQUFhLFdBQVcsQ0FBQztBQUFBLE1BQ25FO0FBRU8sTUFBTSw0QkFBNEIsQ0FBQyxNQUFnQixhQUE0QixNQUFNO0FBQzFGLGNBQU0sYUFBYSxrQkFBa0IsTUFBTSxVQUFVO0FBQ3JELGVBQU8sT0FBTyxlQUFlLFdBQVcsYUFBYSxXQUFXLENBQUM7QUFBQSxNQUNuRTtBQUVPLE1BQU0sNkJBQTZCLElBQUksU0FBNkQ7QUFDekcsY0FBTSxrQkFBb0MsQ0FBQztBQUMzQyxhQUFLLFFBQVEsQ0FBQyxRQUFRO0FBQ3BCLGNBQUksSUFBSSxXQUFXLEdBQUc7QUFDcEIsNEJBQWdCO0FBQUEsY0FDZCxFQUFFLHVCQUF1QixNQUFNLElBQUk7QUFBQSxjQUNuQyxFQUFFLHVCQUF1QixNQUFNLFVBQVUsZUFBZSxHQUFHLEVBQUU7QUFBQSxZQUMvRDtBQUFBLFVBQ0Y7QUFBQSxRQUNGLENBQUM7QUFDRCxlQUFPO0FBQUEsTUFDVDtBQU1PLE1BQU0sbUJBQW1CLENBQUMsU0FBaUI7QUFFaEQsWUFBSSxPQUFPLE1BQU0sR0FBRztBQUNsQixpQkFBTztBQUFBLFFBQ1QsV0FBVyxPQUFPLE1BQU0sR0FBRztBQUN6QixpQkFBTztBQUFBLFFBQ1Q7QUFFQSxlQUFPO0FBQUEsTUFDVDtBQVFPLE1BQU0sYUFBYSxDQUFDLFdBQVcsT0FBTyxZQUFxQixRQUFRLFFBQVE7QUFDaEYsWUFBSSxDQUFDLGNBQWMsZUFBZSxHQUFHO0FBQ25DLGlCQUFPLEdBQUcsUUFBUSxJQUFJLEtBQUs7QUFBQSxRQUM3QjtBQUVBLGVBQU8sTUFBTSxVQUFVLElBQUksUUFBUSxLQUFLLEtBQUs7QUFBQSxNQUMvQztBQVFPLE1BQU0sWUFBWSxDQUFDLFVBQWtCLFlBQW9CLFVBQWtCO0FBQ2hGLFlBQUksYUFBYSxPQUFPO0FBQ3RCLGlCQUFPO0FBQUEsUUFDVDtBQUNBLFlBQUksZUFBZSxHQUFHO0FBQ3BCLGlCQUFPLE9BQU8sS0FBSztBQUFBLFFBQ3JCO0FBRUEsZUFBTyxNQUFNLFVBQVUsU0FBUyxLQUFLO0FBQUEsTUFDdkM7QUFPTyxNQUFNLFlBQVksQ0FBQyxNQUFjLGVBQXVCO0FBQzdELFlBQUksZUFBZSxHQUFHO0FBQ3BCLGlCQUFPLElBQUksSUFBSSxRQUFRLElBQUksUUFBUSxJQUFJLFFBQVEsSUFBSTtBQUFBLFFBQ3JELFdBQVcsZUFBZSxHQUFHO0FBQzNCLGlCQUFPLElBQUksSUFBSSxRQUFRLElBQUk7QUFBQSxRQUM3QixXQUFXLGVBQWUsR0FBRztBQUMzQixpQkFBTyxJQUFJLElBQUksUUFBUSxJQUFJLFFBQVEsSUFBSTtBQUFBLFFBQ3pDO0FBRUEsZUFBTztBQUFBLE1BQ1Q7QUFTTyxNQUFNLGVBQWUsQ0FDMUIsTUFDQSxPQUNBLFFBQ0EsU0FDVztBQUNYLFlBQUksS0FBSyxXQUFXLFdBQVcsS0FBSyxTQUFTLEdBQUc7QUFDOUMsY0FBSSxPQUFPLFVBQVUsVUFBVTtBQUM3QixnQkFBSSxTQUFTLE9BQU87QUFDbEIscUJBQU8sR0FBRyxJQUFJLEtBQUssS0FBSyxXQUFXLEtBQUssZUFBZSxLQUFLO0FBQUEsWUFDOUQsT0FBTztBQUNMLHFCQUFPLEdBQUcsSUFBSSxLQUFLLEtBQUssV0FBVyxLQUFLO0FBQUEsWUFDMUM7QUFBQSxVQUNGLE9BQU87QUFDTCxnQkFBSSxTQUFTLE9BQU87QUFDbEIscUJBQU8sR0FBRyxJQUFJLElBQUksS0FBSyxNQUFNLFFBQVEsQ0FBQyxDQUFDLEtBQUssS0FBSyxNQUFPLFFBQVEsSUFBSyxDQUFDLENBQUMsS0FBTSxRQUFRLElBQUssQ0FBQztBQUFBLFlBQzdGLE9BQU87QUFDTCxxQkFBTyxHQUFHLElBQUksSUFBSSxLQUFLLE1BQU0sUUFBUSxDQUFDLENBQUMsS0FBSyxRQUFRLENBQUM7QUFBQSxZQUN2RDtBQUFBLFVBQ0Y7QUFBQSxRQUNGLE9BQU87QUFDTCxpQkFBTyxTQUFTLElBQUksR0FBRyxJQUFJLElBQUksS0FBSyxNQUFNO0FBQUEsUUFDNUM7QUFBQSxNQUNGO0FBWUEsTUFBTSxzQkFBc0IsQ0FDMUIsTUFDQSxZQUNBLGFBQ0EsT0FDQSxlQUNrQjtBQUNsQixjQUFNLGFBQWEsT0FBTyxnQkFBZ0I7QUFDMUMsY0FBTSxPQUFPLGFBQWEsY0FBYyxZQUFZO0FBQ3BELGNBQU0sZUFBZSxDQUFDLEdBQUcsSUFBSSxNQUFNLElBQUksRUFBRSxLQUFLLENBQUM7QUFDL0MsY0FBTSxjQUFjLE9BQU8sSUFBSSxRQUFRLFFBQVEsSUFBSSxNQUFNLElBQUksVUFBVSxjQUFjLElBQUk7QUFDekYsY0FBTSxhQUFhLGtCQUFrQixZQUFZLFVBQVU7QUFDM0QsY0FBTSxZQUFZLE9BQU8sZUFBZSxXQUFXLGFBQWEsV0FBVyxDQUFDO0FBQzVFLGNBQU0sY0FBYyxPQUFPLGVBQWUsV0FBVyxhQUFhLFdBQVcsQ0FBQztBQUM5RSxjQUFNLE9BQU8sRUFBRSxTQUFTLGFBQWEsT0FBTyxXQUFXLFNBQVMsYUFBYSxRQUFRLFdBQVc7QUFFaEcsY0FBTSxlQUFlLENBQUMsUUFBa0MsT0FBTyxRQUFRLFdBQVcsTUFBTSxHQUFHLEdBQUc7QUFFOUYsY0FBTSxxQkFBcUI7QUFBQSxVQUN6QixpQkFBaUI7QUFBQSxVQUNqQixpQkFBaUI7QUFBQSxVQUNqQiw0QkFBNEI7QUFBQSxVQUM1QixLQUFLO0FBQUEsVUFDTCxjQUFjO0FBQUEsVUFDZCxLQUFLO0FBQUEsVUFDTCxjQUFjO0FBQUEsUUFDaEI7QUFFQSxjQUFNLGdCQUFnQixhQUFhLGNBQWM7QUFDakQsY0FBTSxRQUFRLEdBQUcsYUFBYSxHQUFHLElBQUk7QUFDckMsY0FBTSxVQUFVLEdBQUcsYUFBYSxHQUFHLElBQUk7QUFFdkMsWUFBSSxhQUFhO0FBQ2pCLGlCQUFTLElBQUksR0FBRyxJQUFJLE9BQU8sR0FBRyxLQUFLO0FBQ2pDLHdCQUFjO0FBQUEsYUFDTCxDQUFDLGdCQUFnQixhQUFhLFNBQVMsR0FBRyxJQUFJLENBQUM7QUFBQSxjQUM5QyxDQUFDLGdCQUFnQixhQUFhLFNBQVMsR0FBRyxJQUFJLENBQUM7QUFBQSxjQUMvQyxDQUFDLFVBQVUsQ0FBQztBQUFBLG9CQUNOLENBQUM7QUFBQTtBQUFBLFFBRW5CO0FBQ0Esc0JBQWMsV0FBVyxPQUFPLENBQUM7QUFFakMsY0FBTSxnQ0FDSixPQUFPLElBQ0gsS0FDQTtBQUFBLFdBQ0csSUFBSSxvQkFBb0IsS0FBSyxPQUFPO0FBQUEsbUJBQzVCLEtBQUssT0FBTztBQUFBO0FBQUEsTUFFekIsVUFBVTtBQUFBO0FBQUE7QUFJZCxjQUFNLGtCQUFrQixDQUFDLGNBQXNCO0FBQzdDLDZCQUFtQixrQkFBa0I7QUFDckMsaUJBQU8sT0FBTyxJQUFJLFlBQVksT0FBTyxJQUFJLElBQUksU0FBUztBQUFBLFFBQ3hEO0FBRUEsY0FBTSxVQUFvQixDQUFDO0FBQzNCLFlBQUksUUFBUSxHQUFHO0FBQ2IsbUJBQVMsSUFBSSxPQUFPLEdBQUcsS0FBSyxHQUFHLEtBQUs7QUFDbEMsb0JBQVEsS0FBSyxHQUFHLGFBQWEsU0FBUyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSTtBQUFBLFVBQ3BFO0FBQUEsUUFDRjtBQUVBLGNBQU0sZ0NBQ0osT0FBTyxJQUNILEtBQ0E7QUFBQSxXQUNHLElBQUksYUFBYSxLQUFLLE9BQU87QUFBQSxhQUMzQixRQUFRLEtBQUssR0FBRyxDQUFDO0FBQUE7QUFHNUIsY0FBTSxrQkFBa0IsQ0FBQyxlQUF1QjtBQUM5Qyw2QkFBbUIsa0JBQWtCO0FBQ3JDLGlCQUFPLE9BQU8sSUFBSSxhQUFhLE9BQU8sSUFBSSxJQUFJLFVBQVU7QUFBQSxRQUMxRDtBQUVBLGNBQU0sVUFBVSxJQUFJQyxVQUNsQixTQUFTLElBQUksT0FBTyxHQUFHLEtBQUssT0FBTyxJQUFJQSxNQUFLLElBQUksWUFBWSxFQUFFLEtBQUssR0FBRyxDQUFDO0FBRXpFLGNBQU0sYUFBYSxDQUFDLFlBQW9CLFFBQXlCO0FBQy9ELGNBQUksT0FBTyxHQUFHO0FBQ1osbUJBQU8sR0FBRyxVQUFVO0FBQUEsVUFDdEIsT0FBTztBQUNMLG1CQUFPLEdBQUcsYUFBYSxZQUFZLEtBQUssSUFBSSxDQUFDO0FBQUEsVUFDL0M7QUFBQSxRQUNGO0FBRUEsY0FBTSxhQUFhLENBQUMsWUFBb0IsS0FBc0IsVUFBa0I7QUFDOUUsY0FBSSxPQUFPLEdBQUc7QUFDWixtQkFBTyxHQUFHLFVBQVUsSUFBSSxLQUFLO0FBQUEsVUFDL0IsT0FBTztBQUNMLG1CQUFPLEdBQUcsYUFBYSxZQUFZLEtBQUssSUFBSSxDQUFDLElBQUksS0FBSztBQUFBLFVBQ3hEO0FBQUEsUUFDRjtBQUVBLGNBQU0sMkNBQXNFLENBQUM7QUFDN0UsY0FBTSw2QkFBNkIsQ0FBQyxZQUFvQixXQUEwQjtBQUNoRiw2QkFBbUIsNkJBQTZCO0FBQ2hELGdCQUFNLFVBQVUsR0FBRyxPQUFPLElBQUksdUJBQXVCLElBQUk7QUFDekQsY0FBSSxXQUFXLDBDQUEwQztBQUN2RCxtQkFBTyxHQUFHLE9BQU8sSUFBSSxVQUFVO0FBQUEsVUFDakM7QUFDQSxnQkFBTUMsV0FBVSxDQUFDO0FBQ2pCLG1CQUFTLElBQUksT0FBTyxHQUFHLEtBQUssR0FBRyxLQUFLO0FBQ2xDLGtCQUFNLE1BQU0sT0FBTyxXQUFXLGlCQUFpQixJQUFJLE9BQU8sT0FBTyxJQUFJO0FBQ3JFLFlBQUFBLFNBQVEsS0FBSyxHQUFHLFdBQVcsU0FBUyxDQUFDLENBQUMsT0FBTyxHQUFHLE1BQU0sV0FBVyxPQUFPLENBQUMsQ0FBQyxHQUFHO0FBQUEsVUFDL0U7QUFDQSxtREFBeUMsT0FBTyxJQUFJLE1BQU0sT0FBTyxtQkFBbUIsT0FBTyxLQUFLLE9BQU87QUFBQSxzQkFDckZBLFNBQVEsU0FBUyxJQUFJQSxTQUFRLEtBQUssR0FBRyxJQUFJLElBQUk7QUFBQTtBQUcvRCxpQkFBTyxHQUFHLE9BQU8sSUFBSSxVQUFVO0FBQUEsUUFDakM7QUFFQSxjQUFNLGNBQWMsQ0FBQyxRQUF5QixXQUMzQyxNQUFNO0FBQ0wsY0FBSSxLQUFLLFlBQVksS0FBSyxPQUFPO0FBQy9CLG1CQUFPLEdBQUcsSUFBSSxJQUFJLE1BQU0sS0FBSyxLQUFLO0FBQUEsVUFDcEMsV0FBVyxLQUFLLFlBQVksZUFBZSxLQUFLLFVBQVUsT0FBTztBQUUvRCxtQkFBTyxHQUFHLElBQUksSUFBSSxNQUFNLG1CQUFtQixLQUFLLDhCQUE4QixLQUFLO0FBQUEsVUFDckYsV0FBVyxLQUFLLFlBQVksZUFBZSxLQUFLLFVBQVUsT0FBTztBQUUvRCxtQkFBTyxHQUFHLElBQUksSUFBSSxNQUFNLG1CQUFtQixLQUFLO0FBQUEsVUFDbEQsV0FBVyxLQUFLLFlBQVksU0FBUyxLQUFLLFVBQVUsY0FBYztBQUVoRSxtQkFBTyxHQUFHLElBQUksSUFBSSxNQUFNLDhEQUE4RCxLQUFLO0FBQUEsVUFDN0YsT0FBTztBQUNMLGtCQUFNLElBQUksTUFBTSw2Q0FBNkMsS0FBSyxPQUFPLG1CQUFtQixLQUFLLEtBQUssTUFBTTtBQUFBLFVBQzlHO0FBQUEsUUFDRixHQUFHO0FBRUwsY0FBTSxjQUFjLENBQUMsWUFDbEIsTUFBTTtBQUNMLGNBQUksS0FBSyxZQUFZLEtBQUssT0FBTztBQUMvQixtQkFBTyxHQUFHLElBQUksSUFBSSxNQUFNO0FBQUEsVUFDMUIsV0FBVyxLQUFLLFlBQVksZUFBZSxLQUFLLFVBQVUsT0FBTztBQUUvRCxtQkFBTyxPQUFPLElBQUksSUFBSSxNQUFNO0FBQUEsVUFDOUIsV0FBVyxLQUFLLFlBQVksZUFBZSxLQUFLLFVBQVUsT0FBTztBQUUvRCxtQkFBTyxPQUFPLElBQUksSUFBSSxNQUFNO0FBQUEsVUFDOUIsV0FBVyxLQUFLLFlBQVksU0FBUyxLQUFLLFVBQVUsY0FBYztBQUVoRSxtQkFBTyxtQkFBbUIsSUFBSSxJQUFJLE1BQU0sb0JBQW9CLElBQUksSUFBSSxNQUFNLHNCQUFzQixJQUFJLElBQ2xHLE1BQ0Ysd0JBQXdCLElBQUksSUFBSSxNQUFNO0FBQUEsVUFDeEMsT0FBTztBQUNMLGtCQUFNLElBQUksTUFBTSw2Q0FBNkMsS0FBSyxPQUFPLG1CQUFtQixLQUFLLEtBQUssTUFBTTtBQUFBLFVBQzlHO0FBQUEsUUFDRixHQUFHO0FBRUwsY0FBTSw2QkFDSixPQUFPLElBQ0gsS0FDQTtBQUFBLFdBQ0csSUFBSSxzQkFBc0IsS0FBSyxPQUFPLFFBQVEsU0FBUztBQUFBLGFBQ3JELFlBQVksT0FBTyxJQUFJLFdBQVcsQ0FBQztBQUFBO0FBRzlDLGNBQU0sb0JBQ0osT0FBTyxJQUNILE1BQ0MsTUFBTTtBQUNMLGdCQUFNLGlCQUFpQixhQUFhLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJO0FBQ3RFLGdCQUFNLGFBQWEsYUFBYSxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRSxFQUFFLEtBQUssSUFBSTtBQUM3RCxpQkFBTztBQUFBLFdBQ04sSUFBSSxJQUFJLGNBQWMsUUFBUSxTQUFTO0FBQUEsaUJBQ2pDLElBQUksYUFBYSxRQUFRLFVBQVUsQ0FBQztBQUFBO0FBQUEsUUFFN0MsR0FBRztBQUVULGNBQU0sTUFBTSxJQUFJQyxhQUE0QztBQUMxRCxjQUFJQSxTQUFRLFdBQVcsTUFBTTtBQUMzQixrQkFBTSxJQUFJLE1BQU0sMEJBQTBCLElBQUksRUFBRTtBQUFBLFVBQ2xEO0FBRUEsZ0JBQU0sb0JBQW9CQSxTQUFRLElBQUksWUFBWSxFQUFFLEtBQUssR0FBRztBQUU1RCxjQUFJLFNBQVMsR0FBRztBQUNkLG1CQUFPLFlBQVksSUFBSTtBQUFBLFVBQ3pCLFdBQVcsU0FBUyxHQUFHO0FBQ3JCLG1CQUFPLFlBQVksa0JBQWtCLENBQUMsQ0FBQztBQUFBLFVBQ3pDLE9BQU87QUFDTCwrQkFBbUIsTUFBTTtBQUN6QiwrQkFBbUIsZUFBZTtBQUNsQywrQkFBbUIsa0JBQWtCO0FBQ3JDLG1CQUFPLE9BQU8sSUFBSSxJQUFJLGlCQUFpQjtBQUFBLFVBQ3pDO0FBQUEsUUFDRjtBQUVBLGNBQU0sZUFBZSxDQUFDLGVBQXVCO0FBQzNDLGNBQUksT0FBTyxHQUFHO0FBQ1osbUJBQU8sWUFBWSxVQUFVO0FBQUEsVUFDL0IsT0FBTztBQUNMLCtCQUFtQixlQUFlO0FBQ2xDLCtCQUFtQixrQkFBa0I7QUFDckMsbUJBQU8sT0FBTyxJQUFJLGFBQWEsVUFBVTtBQUFBLFVBQzNDO0FBQUEsUUFDRjtBQUVBLGNBQU0sNkJBQ0osT0FBTyxJQUNILEtBQ0E7QUFBQSxXQUNHLElBQUksc0JBQXNCLEtBQUssT0FBTyxZQUFZLFNBQVM7QUFBQSxNQUNoRSxZQUFZLE9BQU8sSUFBSSxhQUFhLE9BQU8sQ0FBQztBQUFBO0FBR2hELGNBQU0sb0JBQ0osT0FBTyxJQUNILE1BQ0MsTUFBTTtBQUNMLGdCQUFNLGlCQUFpQixhQUFhLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJO0FBQ3RFLGdCQUFNLGFBQWEsYUFBYSxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRSxFQUFFLEtBQUssSUFBSTtBQUM3RCxpQkFBTztBQUFBLFdBQ04sSUFBSSxJQUFJLGNBQWMsWUFBWSxTQUFTO0FBQUEsVUFDNUMsSUFBSSxhQUFhLFFBQVEsVUFBVSxDQUFDO0FBQUE7QUFBQSxRQUV0QyxHQUFHO0FBRVQsY0FBTSxNQUFNLElBQUksb0JBQW9EO0FBQ2xFLGNBQUksZ0JBQWdCLFdBQVcsT0FBTyxHQUFHO0FBQ3ZDLGtCQUFNLElBQUksTUFBTSwwQkFBMEIsSUFBSSxFQUFFO0FBQUEsVUFDbEQ7QUFDQSxnQkFBTSxRQUFRLGdCQUFnQixJQUFJO0FBQ2xDLGNBQUksT0FBTyxVQUFVLFVBQVU7QUFDN0Isa0JBQU0sSUFBSSxNQUFNLHNCQUFzQjtBQUFBLFVBQ3hDO0FBRUEsZ0JBQU0sb0JBQW9CLGdCQUFnQixNQUFNLEdBQUcsSUFBSSxFQUFFLElBQUksWUFBWSxFQUFFLEtBQUssR0FBRztBQUVuRixjQUFJLFNBQVMsR0FBRztBQUNkLG1CQUFPLFlBQVksTUFBTSxLQUFLO0FBQUEsVUFDaEMsV0FBVyxTQUFTLEdBQUc7QUFDckIsbUJBQU8sWUFBWSxrQkFBa0IsQ0FBQyxHQUFHLEtBQUs7QUFBQSxVQUNoRCxPQUFPO0FBQ0wsK0JBQW1CLE1BQU07QUFDekIsK0JBQW1CLGVBQWU7QUFDbEMsK0JBQW1CLGtCQUFrQjtBQUNyQyxtQkFBTyxPQUFPLElBQUksSUFBSSxpQkFBaUIsS0FBSyxLQUFLO0FBQUEsVUFDbkQ7QUFBQSxRQUNGO0FBRUEsY0FBTSxlQUFlLENBQUMsWUFBb0IsVUFBa0I7QUFDMUQsY0FBSSxPQUFPLEdBQUc7QUFDWixtQkFBTyxZQUFZLFlBQVksS0FBSztBQUFBLFVBQ3RDLE9BQU87QUFDTCwrQkFBbUIsZUFBZTtBQUNsQywrQkFBbUIsa0JBQWtCO0FBQ3JDLG1CQUFPLE9BQU8sSUFBSSxhQUFhLFVBQVUsS0FBSyxLQUFLO0FBQUEsVUFDckQ7QUFBQSxRQUNGO0FBRUEsY0FBTSxPQUFPLE1BQU07QUFDakIsZ0JBQU0sUUFBUSxDQUFDO0FBQ2YsY0FBSSxtQkFBbUI7QUFDdkIsY0FBSSxtQkFBbUIsaUJBQWlCO0FBQ3RDLGtCQUFNLEtBQUssNkJBQTZCO0FBQ3hDLCtCQUFtQjtBQUFBLFVBQ3JCO0FBQ0EsY0FBSSxtQkFBbUIsaUJBQWlCO0FBQ3RDLGtCQUFNLEtBQUssNkJBQTZCO0FBQ3hDLCtCQUFtQjtBQUFBLFVBQ3JCO0FBQ0EsY0FBSSxtQkFBbUIsNEJBQTRCO0FBQ2pELG1CQUFPLE9BQU8sd0NBQXdDLEVBQUUsUUFBUSxDQUFDQyxVQUFTLE1BQU0sS0FBS0EsS0FBSSxDQUFDO0FBQzFGLCtCQUFtQjtBQUFBLFVBQ3JCO0FBQ0EsY0FBSSxtQkFBbUIsS0FBSztBQUMxQixrQkFBTSxLQUFLLGlCQUFpQjtBQUM1QiwrQkFBbUI7QUFBQSxVQUNyQjtBQUNBLGNBQUksbUJBQW1CLGNBQWM7QUFDbkMsa0JBQU0sS0FBSywwQkFBMEI7QUFDckMsK0JBQW1CO0FBQUEsVUFDckI7QUFDQSxjQUFJLG1CQUFtQixLQUFLO0FBQzFCLGtCQUFNLEtBQUssaUJBQWlCO0FBQzVCLCtCQUFtQjtBQUFBLFVBQ3JCO0FBQ0EsY0FBSSxtQkFBbUIsY0FBYztBQUNuQyxrQkFBTSxLQUFLLDBCQUEwQjtBQUNyQywrQkFBbUI7QUFBQSxVQUNyQjtBQUNBLGNBQUksQ0FBQyxjQUFjLGtCQUFrQjtBQUNuQyxrQkFBTTtBQUFBLGNBQ0osU0FBUyxLQUFLLE1BQU0sS0FBSyxPQUFPLElBQUksWUFBWSxLQUFLLEdBQUcsQ0FBQztBQUFBLGNBQ3pELFNBQVMsT0FBTyxNQUFNLEtBQUssT0FBTyxJQUFJLFVBQVUsZUFBZSxXQUFXLEVBQUUsS0FBSyxHQUFHLENBQUM7QUFBQSxZQUN2RjtBQUFBLFVBQ0Y7QUFDQSxpQkFBTyxNQUFNLEtBQUssSUFBSTtBQUFBLFFBQ3hCO0FBRUEsZUFBTztBQUFBLFVBQ0w7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUE7QUFBQSxVQUVBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBV08sTUFBTSxnQkFBZ0IsQ0FDM0IsTUFDQSxNQUNBLGFBQ0EsYUFBNEIsTUFDVixvQkFBb0IsTUFBTSxNQUFNLGFBQWEsU0FBUyxVQUFVO0FBVzdFLE1BQU0saUJBQWlCLENBQzVCLE1BQ0EsTUFDQSxhQUNBLGFBQTRCLE1BQ1Ysb0JBQW9CLE1BQU0sTUFBTSxhQUFhLFVBQVUsVUFBVTtBQVU5RSxNQUFNLHVCQUF1QixDQUNsQyxNQUNBLE1BQ0EsZ0JBQ2tCLG9CQUFvQixNQUFNLE1BQU0sYUFBYSxnQkFBZ0IsQ0FBQztBQVczRSxNQUFNLG1CQUFtQixDQUM5QixNQUNBLE1BQ0EsYUFDQSxhQUE0QixNQUNWLG9CQUFvQixNQUFNLE1BQU0sYUFBYSxZQUFZLFVBQVU7QUE4RXZGLE1BQU0sbUJBQU4sTUFBK0M7QUFBQSxRQUM3QyxZQUNVLHlCQUNBLFFBQ1I7QUFGUTtBQUNBO0FBZ0hWLGVBQVEsb0JBQXFDLENBQUM7QUFDOUMsZUFBUSxZQUE2QixDQUFDO0FBQ3RDLGVBQVEsV0FBOEIsQ0FBQztBQXdCdkMsZUFBUSxnQkFBZ0I7QUFBQSxRQXpJckI7QUFBQSxRQUVILHNDQUFzQyxNQUErQjtBQUVuRSxnQkFBTSxhQUFhLE9BQU8sU0FBUyxXQUFXLEdBQUcsSUFBSSxNQUFNO0FBQzNELGlCQUFPLHFCQUFxQixVQUFVO0FBQUEsUUFDeEM7QUFBQSxRQUVBLFVBQVUsZ0JBQW1ELGdCQUFnQjtBQUMzRSxnQkFBTSxpQkFBaUIsT0FBTyxrQkFBa0IsV0FBVyxnQkFBZ0IsY0FBYyxDQUFDO0FBQzFGLGdCQUFNLGlCQUFpQixPQUFPLGtCQUFrQixXQUFXLElBQUksY0FBYyxDQUFDO0FBQzlFLGdCQUFNLGlCQUFpQixPQUFPLGtCQUFrQixXQUFXLElBQUksY0FBYyxDQUFDO0FBRTlFLGNBQ0UsaUJBQWlCLEtBQUssT0FBTyw0QkFDN0IsaUJBQWlCLEtBQUssT0FBTyw0QkFDN0IsaUJBQWlCLEtBQUssT0FBTywwQkFDN0I7QUFDQSxrQkFBTSxJQUFJO0FBQUEsY0FDUixtQkFBbUIsY0FBYyxLQUFLLGNBQWMsS0FDbEQsY0FDRix5Q0FBeUMsS0FBSyxPQUFPLHdCQUF3QixLQUMzRSxLQUFLLE9BQU8sd0JBQ2QsS0FBSyxLQUFLLE9BQU8sd0JBQXdCO0FBQUEsWUFDM0M7QUFBQSxVQUNGO0FBRUEsY0FBSSxpQkFBaUIsaUJBQWlCLGlCQUFpQixLQUFLLE9BQU8sbUNBQW1DO0FBQ3BHLGtCQUFNLElBQUk7QUFBQSxjQUNSLG1CQUFtQixjQUFjLEtBQUssY0FBYyxLQUNsRCxjQUNGLCtDQUErQyxLQUFLLE9BQU8saUNBQWlDO0FBQUEsWUFDOUY7QUFBQSxVQUNGO0FBRUEsZ0JBQU0sdUJBQXVCLEtBQUssd0JBQXdCLENBQUMsTUFBTSxLQUFLLEtBQUssd0JBQXdCLENBQUMsTUFBTTtBQUMxRyxnQkFBTSxZQUFZLHVCQUNkO0FBQUE7QUFBQTtBQUFBLDBEQUlBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFLSixnQkFBTSxzQkFBc0IsdUJBQ3hCO0FBQUEsa0RBRUE7QUFBQTtBQUFBLDhDQUVzQyxpQkFBaUIsaUJBQWlCLGNBQWM7QUFFMUYsaUJBQU8sNEJBQTRCLGNBQWMsS0FBSyxjQUFjLEtBQUssY0FBYztBQUFBLFlBQy9FLFNBQVM7QUFBQSxNQUNmLG1CQUFtQjtBQUFBO0FBQUEsUUFFdkI7QUFBQSxRQUVRLHVCQUF1QixVQUErQjtBQUM1RCxjQUFJLFNBQVMsU0FBUyxHQUFHO0FBQ3ZCLGdCQUFJLFNBQVMsTUFBTSxXQUFXLFdBQVcsR0FBRztBQUMxQyxtQkFBSyxTQUFTLEtBQUssRUFBRSxNQUFNLFNBQVMsTUFBTSxRQUFRLGFBQWEsRUFBRSxHQUFHLE1BQU0sT0FBTyxRQUFRLFNBQVMsS0FBSyxDQUFDO0FBQUEsWUFDMUc7QUFDQSxnQkFBSSxTQUFTLFFBQVEsV0FBVyxXQUFXLEdBQUc7QUFDNUMsbUJBQUssU0FBUyxLQUFLLEVBQUUsTUFBTSxTQUFTLFFBQVEsUUFBUSxhQUFhLEVBQUUsR0FBRyxNQUFNLE9BQU8sUUFBUSxTQUFTLEtBQUssQ0FBQztBQUFBLFlBQzVHO0FBQUEsVUFDRjtBQUFBLFFBQ0Y7QUFBQSxRQUVRLGdCQUFnQixVQUF5QixjQUE4QjtBQUM3RSxjQUFJLFNBQVMsVUFBVSxZQUFZO0FBQ2pDLGtCQUFNLElBQUksTUFBTSwrRkFBK0Y7QUFBQSxVQUNqSDtBQUNBLGVBQUssVUFBVSxLQUFLLFFBQVE7QUFDNUIsZUFBSyx1QkFBdUIsUUFBUTtBQUNwQyxnQkFBTSxTQUFTLFNBQVMsVUFBVSxVQUFVLFNBQVM7QUFDckQsZ0JBQU0sY0FBYyxTQUFTLFVBQVUsaUJBQWlCLGdCQUFnQixTQUFTLEtBQUs7QUFDdEYsaUJBQU8sc0JBQXNCLFlBQVksa0JBQWtCLE1BQU0sS0FBSyxTQUFTLElBQUksV0FBVyxXQUFXO0FBQUEsUUFDM0c7QUFBQSxRQUVBLG9CQUFvQixXQUFvQztBQUN0RCxpQkFBTyxVQUFVLElBQUksQ0FBQyxNQUFNLEtBQUssZ0JBQWdCLEdBQUcsS0FBSyxlQUFlLENBQUMsRUFBRSxLQUFLLElBQUk7QUFBQSxRQUN0RjtBQUFBLFFBRVEseUJBQXlCLFVBQStCO0FBQzlELGNBQUksU0FBUyxVQUFVLFlBQVk7QUFDakMsa0JBQU0sSUFBSTtBQUFBLGNBQ1I7QUFBQSxZQUNGO0FBQUEsVUFDRjtBQUVBLGVBQUssa0JBQWtCLEtBQUssUUFBUTtBQUNwQyxlQUFLLHVCQUF1QixRQUFRO0FBQUEsUUFDdEM7QUFBQSxRQUVBLDZCQUE2QixXQUEwQztBQUNyRSxvQkFBVSxRQUFRLENBQUMsTUFBTSxLQUFLLHlCQUF5QixDQUFDLENBQUM7QUFDekQsaUJBQU87QUFBQSxRQUNUO0FBQUEsUUFFQSxnQkFBZ0IsTUFBYyxNQUE4QixTQUFTLEdBQWlCO0FBQ3BGLGVBQUssU0FBUyxLQUFLLEVBQUUsTUFBTSxNQUFNLE9BQU8sQ0FBQztBQUN6QyxpQkFBTztBQUFBLFFBQ1Q7QUFBQSxRQUVBLGlCQUFpQixvQkFBcUQ7QUFDcEUsZUFBSyxXQUFXLEtBQUssU0FBUyxPQUFPLGtCQUFrQjtBQUN2RCxpQkFBTztBQUFBLFFBQ1Q7QUFBQSxRQUtRLHFCQUE2QjtBQUNuQyxjQUFJLEtBQUssU0FBUyxXQUFXLEdBQUc7QUFDOUIsbUJBQU87QUFBQSxVQUNUO0FBRUEsZ0JBQU0sa0JBQTRCLENBQUM7QUFDbkMscUJBQVcsRUFBRSxNQUFNLE1BQU0sT0FBTyxLQUFLLEtBQUssVUFBVTtBQUNsRCxnQkFBSSxVQUFVLFNBQVMsR0FBRztBQUN4QixrQkFBSSxTQUFTLE9BQU87QUFDbEIsZ0NBQWdCLEtBQUssY0FBYyxJQUFJLGlCQUFpQixJQUFJLE1BQU0sS0FBSyxLQUFLLFNBQVMsQ0FBQyxDQUFDLEdBQUc7QUFBQSxjQUM1RixPQUFPO0FBQ0wsZ0NBQWdCLEtBQUssR0FBRyxJQUFJLGVBQWUsSUFBSSxNQUFNLEtBQUssS0FBSyxTQUFTLENBQUMsQ0FBQyxHQUFHO0FBQUEsY0FDL0U7QUFBQSxZQUNGLE9BQU87QUFDTCxvQkFBTSxXQUFXLFVBQVUsUUFBUSxXQUFXLElBQUksT0FBTyxNQUFNLE1BQU0sSUFBSSxJQUFJO0FBQzdFLDhCQUFnQixLQUFLLEdBQUcsSUFBSSxJQUFJLFFBQVEsRUFBRTtBQUFBLFlBQzVDO0FBQUEsVUFDRjtBQUVBLGlCQUFPO0FBQUEsMEJBQ2UsZ0JBQWdCLEtBQUssSUFBSSxDQUFDO0FBQUEsMkJBQ3pCLEtBQUssYUFBYTtBQUFBLFFBQzNDO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFNQSxJQUFJLDRCQUFvQztBQUN0QyxpQkFDRSxLQUFLLG1CQUFtQixJQUN4QixLQUFLLFVBQVUsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsRUFBRSxLQUFLLElBQUksSUFDN0MsS0FBSyxrQkFBa0IsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsRUFBRSxLQUFLLElBQUk7QUFBQSxRQUV6RDtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBS0EsSUFBSSxnQkFBMEQ7QUFDNUQsY0FBSSxLQUFLLFNBQVMsV0FBVyxHQUFHO0FBQzlCLG1CQUFPO0FBQUEsVUFDVDtBQUVBLGdCQUFNLDRCQUE0QixDQUFDLFNBQ2pDLGdFQUFrRSxFQUFFLENBQUMsT0FBTyxPQUFPLE9BQU8sS0FBSyxFQUFFLFFBQVEsSUFBSSxDQUFDO0FBQ2hILGlCQUFPLEtBQUssU0FBUyxJQUFJLENBQUMsTUFBTSxDQUFDLDBCQUEwQixFQUFFLElBQUksR0FBRyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0FBQUEsUUFDcEY7QUFBQSxNQUNGO0FBRU8sTUFBTSxxQkFBcUIsQ0FBQyxlQUF5QyxXQUMxRSxJQUFJLGlCQUFpQixlQUFlLE1BQU07QUFBQTtBQUFBOzs7QUNsL0I1QyxNQWVNLGdCQVVBLGlCQUdBLGdCQUdBLGtCQVdBLGNBY0Esb0JBZ0JPLDRCQTRIQSxXQUtBO0FBek1iO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFDQTtBQUdBO0FBTUEsTUFBTSxpQkFBaUIsQ0FBQyxRQUErQixTQUFrQztBQUN2RixZQUFJLENBQUMsVUFBVSxPQUFPLFdBQVcsR0FBRztBQUNsQyxnQkFBTSxJQUFJLE1BQU0sNkJBQTZCO0FBQUEsUUFDL0M7QUFFQSxZQUFJLEtBQUssV0FBVyxLQUFLLEtBQUssV0FBVyxPQUFPLENBQUMsRUFBRSxLQUFLLFFBQVE7QUFDOUQsZ0JBQU0sSUFBSSxNQUFNLGFBQWEsS0FBSyxNQUFNLDhCQUE4QixPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU0sRUFBRTtBQUFBLFFBQy9GO0FBQUEsTUFDRjtBQUVBLE1BQU0sa0JBQWtCLENBQUMsV0FBbUIsU0FDMUMsS0FBSyxXQUFXLElBQUksT0FBTyxDQUFDLEdBQUcsSUFBSSxNQUFNLFNBQVMsRUFBRSxLQUFLLENBQUMsRUFBRSxRQUFRO0FBRXRFLE1BQU0saUJBQWlCLENBQUMsWUFBK0IsU0FDckQsVUFBVSxnQkFBZ0IsWUFBWSxnQkFBZ0IsV0FBVyxRQUFRLElBQUksQ0FBQztBQUVoRixNQUFNLG1CQUFtQixDQUFDLE1BQWdCLE1BQWMsT0FBc0IsV0FBa0M7QUFDOUcsWUFBSSxjQUFjLGNBQWMsT0FBTyxLQUFLLE9BQU8sUUFBUSxNQUFNLEtBQUssT0FBTztBQUFBLGFBQ2xFLE1BQU0sS0FBSyxPQUFPO0FBQzdCLGlCQUFTLElBQUksR0FBRyxJQUFJLE1BQU0sRUFBRSxHQUFHO0FBRzdCLHlCQUFlLEtBQUssS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDO0FBQUEsUUFDckM7QUFDQSxlQUFRLGVBQWU7QUFBQSxNQUN6QjtBQUVBLE1BQU0sZUFBZSxDQUFDLE9BQTBCLGlCQUFzRTtBQUNwSCxjQUFNLFdBQXFCLENBQUM7QUFDNUIsY0FBTSxVQUFvQixDQUFDO0FBQzNCLGlCQUFTLElBQUksR0FBRyxJQUFJLE1BQU0sUUFBUSxFQUFFLEdBQUc7QUFDckMsY0FBSSxNQUFNLENBQUMsTUFBTSxHQUFHO0FBQ2xCLHFCQUFTLEtBQUssTUFBTSxDQUFDLENBQUM7QUFBQSxVQUN4QjtBQUNBLGNBQUksTUFBTSxhQUFhLENBQUMsQ0FBQyxNQUFNLEdBQUc7QUFDaEMsb0JBQVEsS0FBSyxhQUFhLENBQUMsQ0FBQztBQUFBLFVBQzlCO0FBQUEsUUFDRjtBQUNBLGVBQU8sRUFBRSxVQUFVLFFBQVE7QUFBQSxNQUM3QjtBQUVBLE1BQU0scUJBQXFCLENBQUMsTUFBZ0IsVUFBNkI7QUFHdkUsWUFBSSxtQkFBbUI7QUFDdkIsaUJBQVMsSUFBSSxHQUFHLElBQUksS0FBSyxRQUFRLEVBQUUsR0FBRztBQUNwQyxjQUFJLE1BQU0sS0FBSyxDQUFDLENBQUMsTUFBTSxHQUFHO0FBQ3hCO0FBQUEsVUFDRjtBQUNBLGNBQUksS0FBSyxDQUFDLElBQUksa0JBQWtCO0FBQzlCLG1CQUFPO0FBQUEsVUFDVDtBQUNBLDZCQUFtQixLQUFLLENBQUM7QUFBQSxRQUMzQjtBQUNBLGVBQU87QUFBQSxNQUNUO0FBRU8sTUFBTSw2QkFBNkIsQ0FBQyxhQUF5QixhQUFvQztBQUN0RyxjQUFNLGdCQUFnQixZQUFZO0FBQ2xDLGNBQU0sWUFBWSxZQUFZLEtBQUs7QUFDbkMsY0FBTSxPQUFPLGdCQUFnQixXQUFXLFFBQVE7QUFDaEQsY0FBTSxjQUFjLGVBQWUsWUFBWSxNQUFNLElBQUk7QUFDekQsWUFBSSxnQkFBZ0IsWUFBWTtBQUNoQyxZQUFJLGlCQUFpQjtBQUNyQixjQUFNLHFCQUFxQixZQUFZLEtBQUssbUJBQW1CLE1BQU0sWUFBWSxJQUFJO0FBQ3JGLFlBQUk7QUFDSixZQUFJLG9CQUFvQjtBQUN0Qiw0QkFBa0IsQ0FBQyxpQkFBK0I7QUFDaEQsa0JBQU0sUUFBUSxjQUFjLFNBQVMsZUFBZSxlQUFlLENBQUM7QUFDcEUsa0JBQU0sU0FBUyxlQUFlLFVBQVUsZUFBZSxnQkFBZ0IsQ0FBQztBQUN4RSxtQkFBTztBQUFBLElBQ1QsYUFBYSxnQkFBZ0IsZUFBZSxLQUFLLEVBQUUsaUJBQWlCLE9BQU8sTUFBTSxDQUFDO0FBQUEsSUFDbEYsYUFBYSxVQUFVLENBQUM7QUFBQSxNQUN0QixhQUFhLHNDQUFzQyxzQkFBc0IsQ0FBQztBQUFBO0FBQUE7QUFBQSxVQUc1RTtBQUVBLGlCQUFPO0FBQUEsWUFDTCxNQUFNO0FBQUEsWUFDTixhQUFhLEVBQUUsbUJBQW1CLENBQUMsTUFBTSxFQUFFO0FBQUEsWUFDM0MsWUFBWSxNQUFNO0FBQ2hCLG9CQUFNLGFBQWEsVUFBVSxLQUFLLFdBQVc7QUFDN0MscUJBQU87QUFBQSxnQkFDTCxTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxZQUFZLFNBQVMsQ0FBQztBQUFBLGdCQUMvRCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsa0JBQUssYUFBYSxLQUEwQjtBQUFBO0FBQUEsZ0JBQWtCLEVBQUU7QUFBQSxnQkFDekYsaUJBQWlCLENBQUMsRUFBRSx1QkFBdUIsTUFBTSxLQUFLLEtBQUssYUFBYSxDQUFDLEVBQUUsQ0FBQztBQUFBLGNBQzlFO0FBQUEsWUFDRjtBQUFBLFlBQ0E7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUNBLGNBQU0sRUFBRSxVQUFVLFFBQVEsSUFBSSxhQUFhLFlBQVksTUFBTSxJQUFJO0FBQ2pFLGNBQU0sZUFBZSxVQUFVLFNBQVMsU0FBUyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUM7QUFDMUQsY0FBTSxnQkFBZ0IsVUFBVSxTQUFTLFNBQVMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0FBQzNELGNBQU0sWUFBWSxTQUFTLFdBQVcsS0FBSyxnQkFBZ0I7QUFDM0QsWUFBSSxXQUFXO0FBQ2IsMEJBQWdCLGVBQ1osQ0FBQyxTQUFTLENBQUMsR0FBRyxTQUFTLENBQUMsSUFBSSxTQUFTLENBQUMsQ0FBQyxJQUN2QyxnQkFDRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLFNBQVMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFDLElBQ3ZDO0FBQ04sMkJBQWlCLENBQUMsY0FBYyxDQUFDLEdBQUcsY0FBYyxDQUFDLENBQUM7QUFDcEQsZ0JBQU0sV0FBVztBQUNqQiw0QkFBa0IsQ0FBQyxpQkFBK0I7QUFDaEQsa0JBQU0sUUFBUSxjQUFjLEtBQUssZUFBZSxjQUFjLE1BQU07QUFDcEUsa0JBQU0sU0FBUyxlQUFlLFVBQVUsZUFBZSxlQUFlLE1BQU07QUFDNUUsbUJBQU87QUFBQSxJQUNULGFBQWEsZ0JBQWdCLGVBQWUsS0FBSyxFQUFFLGlCQUFpQixPQUFPLE1BQU0sQ0FBQztBQUFBLHNDQUNoRCxPQUFPLEtBQUssS0FBSyxLQUFLLFdBQVcsQ0FBQyxNQUFNLFFBQVE7QUFBQSxJQUNsRixhQUFhLFVBQVUsQ0FBQyxVQUFVLFVBQVUsQ0FBQyxDQUFDLENBQUM7QUFBQSxvREFDQyxRQUFRO0FBQUE7QUFBQTtBQUFBLHVDQUdyQixRQUFRO0FBQUEsdUNBQ1IsUUFBUTtBQUFBO0FBQUEsdUNBRVIsTUFBTSxhQUFhLEdBQUcsTUFBTSxLQUFLLE9BQU8sd0JBQXdCLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQSx3Q0FJaEUsUUFBUTtBQUFBLHdDQUNSLFFBQVE7QUFBQTtBQUFBLFFBRXhDLE9BQU8sYUFBYSxHQUFHLE9BQU8sS0FBSyxPQUFPLDRCQUE0Qiw4QkFBOEIsQ0FBQztBQUFBO0FBQUE7QUFBQSxVQUd6RztBQUNBLGlCQUFPO0FBQUEsWUFDTCxNQUFNO0FBQUEsWUFDTixhQUFhLEVBQUUsbUJBQW1CLENBQUMsTUFBTSxFQUFFO0FBQUEsWUFDM0MsWUFBWSxNQUFNO0FBQ2hCLG9CQUFNLGFBQWEsVUFBVSxLQUFLLFdBQVc7QUFDN0MscUJBQU87QUFBQSxnQkFDTCxTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxZQUFZLFNBQVMsQ0FBQztBQUFBLGdCQUMvRCxlQUFlLEVBQUUsR0FBRyxLQUFLLEtBQUssZUFBZSxDQUFDLElBQUksUUFBUSxHQUFHLEdBQUcsS0FBSyxLQUFLLGVBQWUsQ0FBQyxJQUFJLFFBQVEsRUFBRTtBQUFBLGdCQUN4RyxpQkFBaUI7QUFBQSxrQkFDZixFQUFFLHVCQUF1QixNQUFNLFdBQVc7QUFBQSxrQkFDMUMsR0FBRywyQkFBMkIsZUFBZSxjQUFjO0FBQUEsZ0JBQzdEO0FBQUEsY0FDRjtBQUFBLFlBQ0Y7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUFBLFFBQ0Y7QUFFQSwwQkFBa0IsQ0FBQyxpQkFBK0I7QUFDaEQsZ0JBQU0sUUFBUSxjQUFjLEtBQUssZUFBZSxjQUFjLE1BQU07QUFDcEUsZ0JBQU0sU0FBUyxlQUFlLFVBQVUsZUFBZSxlQUFlLE1BQU07QUFDNUUsaUJBQU87QUFBQSxJQUNQLGFBQWEsZ0JBQWdCLGVBQWUsS0FBSyxFQUFFLGlCQUFpQixPQUFPLE1BQU0sQ0FBQztBQUFBO0FBQUEsSUFFbEYsaUJBQWlCLE1BQU0sV0FBVyxPQUFPLE1BQU0sQ0FBQztBQUFBO0FBQUEsSUFFaEQsYUFBYSxVQUFVLENBQUM7QUFBQSxNQUN0QixhQUFhLHNDQUFzQyxzQkFBc0IsQ0FBQztBQUFBO0FBQUEsb0JBRTVELE9BQU8sZ0JBQWdCLFlBQVksQ0FBQztBQUFBO0FBQUE7QUFBQSxNQUdsRCxPQUFPLFlBQVksY0FBYyxNQUFNLGFBQWEsVUFBVSxDQUFDLENBQUM7QUFBQTtBQUFBLFFBRXBFO0FBQ0EsZUFBTztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sYUFBYSxFQUFFLE1BQU0sR0FBRyxRQUFRLElBQUksbUJBQW1CLENBQUMsTUFBTSxFQUFFO0FBQUEsVUFDaEUsWUFBWSxNQUFNO0FBQ2hCLGtCQUFNLGFBQWEsVUFBVSxLQUFLLFdBQVc7QUFDN0MsbUJBQU87QUFBQSxjQUNMLFNBQVMsQ0FBQyxFQUFFLE1BQU0sYUFBYSxVQUFVLFlBQVksU0FBUyxDQUFDO0FBQUEsY0FDL0QsZUFBZSxFQUFFLEdBQUcsS0FBSztBQUFBLGdCQUFLLGFBQWE7QUFBQTtBQUFBLGNBQXVCLEVBQUU7QUFBQSxjQUNwRSxpQkFBaUI7QUFBQSxnQkFDZixFQUFFLHVCQUF1QixNQUFNLFdBQVc7QUFBQSxnQkFDMUMsR0FBRywyQkFBMkIsZUFBZSxjQUFjO0FBQUEsY0FDN0Q7QUFBQSxZQUNGO0FBQUEsVUFDRjtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sWUFBWSxDQUFDLFNBQXlCLGVBQTBDO0FBQzNGLHVCQUFlLFFBQVEsUUFBUSxXQUFXLElBQUk7QUFDOUMsZ0JBQVEsUUFBUSwyQkFBMkIsUUFBUSxPQUFPLENBQUMsR0FBRyxXQUFXLElBQUksQ0FBQztBQUFBLE1BQ2hGO0FBRU8sTUFBTSwyQkFBMkIsQ0FBQyxlQUN2Qyw0QkFBNEIsRUFBRSxNQUFNLFdBQVcsS0FBaUIsQ0FBQztBQUFBO0FBQUE7OztBQzFNbkUsTUFZTSxXQWFBLGlCQWFBLGtCQWFBLG9CQVlBLGtCQVFBLDJCQVlBLHNCQWNBLHNCQVNBLG9CQWFPLCtCQXNGUCxjQThDTyxrQkFJQSxnQkFJQSxnQkFJQSx1QkFJQSxpQkFJQSxpQkFJQSxrQkFJQSxpQkFJQSx1QkFJQTtBQS9SYjtBQUFBO0FBQUE7QUFHQTtBQUVBO0FBR0E7QUFDQTtBQUNBO0FBRUEsTUFBTSxZQUF1QztBQUFBLFFBQzNDLEtBQUs7QUFBQSxRQUNMLEtBQUs7QUFBQSxRQUNMLE1BQU07QUFBQSxRQUNOLEtBQUs7QUFBQSxRQUNMLE1BQU07QUFBQSxRQUNOLFdBQVc7QUFBQSxRQUNYLFdBQVc7QUFBQSxRQUNYLElBQUk7QUFBQSxRQUNKLElBQUk7QUFBQSxRQUNKLFFBQVE7QUFBQSxNQUNWO0FBRUEsTUFBTSxrQkFBNkM7QUFBQSxRQUNqRCxLQUFLO0FBQUEsUUFDTCxLQUFLO0FBQUEsUUFDTCxNQUFNO0FBQUEsUUFDTixLQUFLO0FBQUEsUUFDTCxNQUFNO0FBQUEsUUFDTixXQUFXO0FBQUEsUUFDWCxXQUFXO0FBQUEsUUFDWCxJQUFJO0FBQUEsUUFDSixJQUFJO0FBQUEsUUFDSixRQUFRO0FBQUEsTUFDVjtBQUVBLE1BQU0sbUJBQThDO0FBQUEsUUFDbEQsS0FBSztBQUFBLFFBQ0wsS0FBSztBQUFBLFFBQ0wsTUFBTTtBQUFBLFFBQ04sS0FBSztBQUFBLFFBQ0wsTUFBTTtBQUFBLFFBQ04sV0FBVztBQUFBLFFBQ1gsV0FBVztBQUFBLFFBQ1gsSUFBSTtBQUFBLFFBQ0osSUFBSTtBQUFBLFFBQ0osUUFBUTtBQUFBLE1BQ1Y7QUFFQSxNQUFNLHFCQUFnRDtBQUFBLFFBQ3BELEtBQUs7QUFBQSxRQUNMLEtBQUs7QUFBQSxRQUNMLEtBQUs7QUFBQSxRQUNMLE1BQU07QUFBQSxRQUNOLFdBQVc7QUFBQSxRQUNYLFdBQVc7QUFBQSxRQUNYLElBQUk7QUFBQSxRQUNKLElBQUk7QUFBQSxRQUNKLFFBQVE7QUFBQSxNQUNWO0FBRUEsTUFBTSxtQkFBbUIsQ0FBQyxjQUFzQixTQUEyQjtBQUN6RSxjQUFNLE1BQU0sQ0FBQztBQUNiLGlCQUFTLElBQUksT0FBTyxjQUFjLElBQUksTUFBTSxFQUFFLEdBQUc7QUFDL0MsY0FBSSxLQUFLLENBQUM7QUFBQSxRQUNaO0FBQ0EsZUFBTztBQUFBLE1BQ1Q7QUFFQSxNQUFNLDRCQUE0QixDQUFDLE9BQTBCLFNBQWtEO0FBQzdHLGNBQU0sY0FBYyxDQUFDO0FBQ3JCLGNBQU0sT0FBTyxNQUFNO0FBQ25CLGlCQUFTLE1BQU0sR0FBRyxNQUFNLE1BQU0sT0FBTztBQUNuQyxjQUFJLEtBQUssUUFBUSxHQUFHLE1BQU0sSUFBSTtBQUM1Qix3QkFBWSxLQUFLLE1BQU0sR0FBRyxDQUFDO0FBQUEsVUFDN0I7QUFBQSxRQUNGO0FBQ0EsY0FBTSxjQUFjLEtBQUssSUFBSSxDQUFDLFFBQVEsTUFBTSxHQUFHLENBQUM7QUFDaEQsZUFBTyxDQUFDLGFBQWEsV0FBVztBQUFBLE1BQ2xDO0FBRUEsTUFBTSx1QkFBdUIsQ0FBQyxPQUFpQixTQUE2QjtBQUMxRSxjQUFNLE9BQU8sTUFBTSxTQUFTLEtBQUs7QUFDakMsY0FBTSxjQUFjLENBQUM7QUFDckIsWUFBSSxXQUFXO0FBQ2YsaUJBQVMsTUFBTSxHQUFHLE1BQU0sTUFBTSxPQUFPO0FBQ25DLGNBQUksS0FBSyxRQUFRLEdBQUcsTUFBTSxJQUFJO0FBQzVCLHdCQUFZLEtBQUssTUFBTSxVQUFVLENBQUM7QUFBQSxVQUNwQyxPQUFPO0FBQ0wsd0JBQVksS0FBSyxDQUFDO0FBQUEsVUFDcEI7QUFBQSxRQUNGO0FBQ0EsZUFBTztBQUFBLE1BQ1Q7QUFFQSxNQUFNLHVCQUF1QixDQUFDLE1BQWdCLFNBQTBCO0FBQ3RFLGlCQUFTLElBQUksR0FBRyxJQUFJLEtBQUssUUFBUSxFQUFFLEdBQUc7QUFDcEMsY0FBSSxLQUFLLEtBQUssU0FBUyxJQUFJLENBQUMsTUFBTSxPQUFPLElBQUksR0FBRztBQUM5QyxtQkFBTztBQUFBLFVBQ1Q7QUFBQSxRQUNGO0FBQ0EsZUFBTztBQUFBLE1BQ1Q7QUFFQSxNQUFNLHFCQUFxQixDQUFDLE1BQWdCLFNBQTJCO0FBQ3JFLGNBQU0sTUFBTSxDQUFDO0FBQ2IsWUFBSSxDQUFDLHFCQUFxQixNQUFNLElBQUksR0FBRztBQUNyQyxtQkFBUyxJQUFJLEdBQUcsSUFBSSxNQUFNLEVBQUUsR0FBRztBQUM3QixnQkFBSSxLQUFLLFFBQVEsQ0FBQyxNQUFNLElBQUk7QUFDMUIsa0JBQUksS0FBSyxDQUFDO0FBQUEsWUFDWjtBQUFBLFVBQ0Y7QUFDQSxlQUFLLFFBQVEsQ0FBQyxTQUFTLElBQUksS0FBSyxJQUFJLENBQUM7QUFBQSxRQUN2QztBQUNBLGVBQU87QUFBQSxNQUNUO0FBRU8sTUFBTSxnQ0FBZ0MsQ0FDM0MsTUFDQSxVQUNBLFFBQ0EsWUFDQSxnQkFDQSxhQUNBLGdCQUNnQjtBQUNoQixjQUFNLGFBQWEsT0FBTyxDQUFDLEVBQUU7QUFFN0IsY0FBTSxhQUFhLFVBQVUsS0FBSyxXQUFXO0FBQzdDLGNBQU0sYUFBYSxVQUFVLEtBQUssV0FBVztBQUU3QyxjQUFNLFFBQVEsY0FBYyxNQUFNLE9BQU8sQ0FBQyxFQUFFLFVBQVUsVUFBVTtBQUNoRSxjQUFNLFNBQVMsZUFBZSxVQUFVLGdCQUFnQixXQUFXO0FBRW5FLFlBQUksZ0JBQWdCO0FBRXBCLFlBQUksZUFBZSxHQUFHO0FBQ3BCLDBCQUFnQjtBQUFBLFFBQ2xCO0FBRUEsY0FBTSxzQkFBc0I7QUFBQSxvREFDc0IsYUFBYTtBQUFBO0FBRy9ELGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQUEsVUFDaEQsYUFBYSxnQkFBZ0IsY0FBYyxLQUFLLEVBQUUsaUJBQWlCLE9BQU8sTUFBTSxDQUFDO0FBQUEsVUFDakYsbUJBQW1CO0FBQUE7QUFBQTtBQUFBO0FBQUEsV0FJbEIsYUFBYSxVQUFVLGFBQWEsQ0FBQztBQUFBO0FBQUEsMkNBRUwsYUFBYTtBQUFBO0FBQUE7QUFBQSxnQ0FHeEIsaUJBQWlCLFVBQVUsQ0FBQztBQUFBO0FBQUEsd0RBRUosYUFBYTtBQUFBLGlDQUNwQyxNQUFNLFlBQVksWUFBWSxDQUFDO0FBQUEseUJBQ3ZDLFVBQVUsVUFBVSxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSx3Q0FLTixhQUFhO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLDBCQU0zQixnQkFBZ0IsVUFBVSxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxZQVF6QyxPQUFPO0FBQUEsVUFDUDtBQUFBLFVBQ0EsR0FDRSxlQUFlLFNBQ1gsR0FBRyxPQUFPLEtBQUssT0FBTywyQ0FDdEIsR0FBRyxPQUFPLEtBQUssT0FBTyxJQUFJLG1CQUFtQixVQUFVLENBQUMsR0FDOUQ7QUFBQSxRQUNGLENBQUM7QUFBQTtBQUFBO0FBS1QsZUFBTztBQUFBLFVBQ0w7QUFBQTtBQUFBLFVBRUEsYUFBYSxFQUFFLE1BQU0sR0FBRyxRQUFRLElBQUksYUFBYSxJQUFJLG1CQUFtQixDQUFDLE1BQU0sRUFBRTtBQUFBLFVBQ2pGO0FBQUEsVUFDQSxZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxlQUFlLENBQUM7QUFBQSxZQUN6RCxlQUFlLEVBQUUsR0FBRyxXQUFXO0FBQUEsWUFDL0IsaUJBQWlCLENBQUMsRUFBRSx1QkFBdUIsTUFBTSxXQUFXLENBQUM7QUFBQSxVQUMvRDtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRUEsTUFBTSxlQUFlLENBQ25CLFNBQ0EsTUFDQSxZQUNBLGVBQ1M7QUFDVCxjQUFNLG9CQUNKLFFBQVEsT0FBTyxXQUFXLElBQUksYUFBYSxpQ0FBaUMsUUFBUSxRQUFRLFVBQVU7QUFFeEcsWUFBSSxjQUFjLGtCQUFrQjtBQUNwQyxZQUFJLFlBQVksV0FBVyxLQUFLLENBQUMsa0JBQWtCLG1CQUFtQjtBQUNwRSx3QkFBYyxRQUFRLE9BQU8sQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLE1BQU0sTUFBTSxDQUFDO0FBQUEsUUFDekQ7QUFDQSxjQUFNLGdCQUFnQixVQUFVLGNBQWMsYUFBYSxRQUFRLE9BQU8sQ0FBQyxFQUFFLEtBQUssTUFBTTtBQUV4RixZQUFJLE9BQU87QUFDWCxZQUFJLFFBQVEsUUFBUSxPQUFPLENBQUM7QUFDNUIsY0FBTSxlQUFlLG1CQUFtQixNQUFNLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxNQUFNO0FBQzNFLFlBQUksYUFBYSxTQUFTLEdBQUc7QUFDM0Isa0JBQVEsUUFBUSxRQUFRLDJCQUEyQixRQUFRLE9BQU8sQ0FBQyxHQUFHLFlBQVksR0FBRztBQUFBLFlBQ25GLFFBQVEsQ0FBQyxDQUFDO0FBQUEsWUFDVixTQUFTLENBQUMsRUFBRTtBQUFBLFVBQ2QsQ0FBQyxFQUFFLENBQUM7QUFDSixpQkFBTyxpQkFBaUIsS0FBSyxRQUFRLE1BQU0sS0FBSyxNQUFNO0FBQUEsUUFDeEQ7QUFFQSxjQUFNLENBQUMsYUFBYSxXQUFXLElBQUksMEJBQTBCLE1BQU0sTUFBTSxJQUFJO0FBQzdFLFlBQUksbUJBQW1CO0FBQ3ZCLFlBQUksa0JBQWtCLFVBQVU7QUFDOUIsNkJBQW1CLHFCQUFxQixhQUFhLGFBQWE7QUFBQSxRQUNwRTtBQUVBLGdCQUFRO0FBQUEsVUFDTjtBQUFBLFlBQ0U7QUFBQSxZQUNBLGtCQUFrQjtBQUFBLFlBQ2xCLENBQUMsS0FBSztBQUFBLFlBQ047QUFBQSxZQUNBLFFBQVEsT0FBTyxDQUFDLEVBQUU7QUFBQSxZQUNsQjtBQUFBLFlBQ0E7QUFBQSxVQUNGO0FBQUEsVUFDQSxFQUFFLFFBQVEsQ0FBQyxLQUFLLEVBQUU7QUFBQSxRQUNwQjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLG1CQUFtQixDQUFDLFNBQXlCLGVBQXVDO0FBQy9GLHFCQUFhLFNBQVMsb0JBQW9CLFlBQVksTUFBTTtBQUFBLE1BQzlEO0FBRU8sTUFBTSxpQkFBaUIsQ0FBQyxTQUF5QixlQUF1QztBQUM3RixxQkFBYSxTQUFTLGtCQUFrQixZQUFZLElBQUk7QUFBQSxNQUMxRDtBQUVPLE1BQU0saUJBQWlCLENBQUMsU0FBeUIsZUFBdUM7QUFDN0YscUJBQWEsU0FBUyxrQkFBa0IsWUFBWSxJQUFJO0FBQUEsTUFDMUQ7QUFFTyxNQUFNLHdCQUF3QixDQUFDLFNBQXlCLGVBQXVDO0FBQ3BHLHFCQUFhLFNBQVMseUJBQXlCLFlBQVksV0FBVztBQUFBLE1BQ3hFO0FBRU8sTUFBTSxrQkFBa0IsQ0FBQyxTQUF5QixlQUF1QztBQUM5RixxQkFBYSxTQUFTLG1CQUFtQixZQUFZLEtBQUs7QUFBQSxNQUM1RDtBQUVPLE1BQU0sa0JBQWtCLENBQUMsU0FBeUIsZUFBdUM7QUFDOUYscUJBQWEsU0FBUyxtQkFBbUIsWUFBWSxLQUFLO0FBQUEsTUFDNUQ7QUFFTyxNQUFNLG1CQUFtQixDQUFDLFNBQXlCLGVBQXVDO0FBQy9GLHFCQUFhLFNBQVMsb0JBQW9CLFlBQVksTUFBTTtBQUFBLE1BQzlEO0FBRU8sTUFBTSxrQkFBa0IsQ0FBQyxTQUF5QixlQUF1QztBQUM5RixxQkFBYSxTQUFTLG1CQUFtQixZQUFZLEtBQUs7QUFBQSxNQUM1RDtBQUVPLE1BQU0sd0JBQXdCLENBQUMsU0FBeUIsZUFBdUM7QUFDcEcscUJBQWEsU0FBUyx5QkFBeUIsWUFBWSxXQUFXO0FBQUEsTUFDeEU7QUFFTyxNQUFNLHFCQUFxQixDQUFDLFNBQXlCLGVBQXVDO0FBQ2pHLHFCQUFhLFNBQVMsc0JBQXNCLFlBQVksUUFBUTtBQUFBLE1BQ2xFO0FBQUE7QUFBQTs7O0FDalNBLE1BdUJNQyxpQkFzQkEsTUFDTyx5QkFvRkEsa0NBZVAsa0JBeUJBLG1CQVdBLGVBV0EsZUFXQSxzQkFXQSxnQkFvQkEsaUJBcUJBLGdCQW9CQSxpQkFXQSxnQkFXQSxzQkFXQSxzQkF5Qk8sWUFRQSxVQVFBLFVBUUEsaUJBUUEsV0FRQSxXQVFBLFlBUUEsV0FRQSxpQkFRQTtBQXJaYjtBQUFBO0FBQUE7QUFHQTtBQUVBO0FBQ0E7QUFHQTtBQUNBO0FBYUEsTUFBTUEsa0JBQWlCLENBQUMsV0FBd0M7QUFDOUQsWUFBSSxDQUFDLFVBQVUsT0FBTyxXQUFXLEtBQUssT0FBTyxTQUFTLEdBQUc7QUFDdkQsZ0JBQU0sSUFBSSxNQUFNLG1DQUFtQztBQUFBLFFBQ3JEO0FBRUEsWUFBSSxPQUFPLFdBQVcsS0FBSyxPQUFPLENBQUMsRUFBRSxLQUFLLFdBQVcsR0FBRztBQUN0RCxnQkFBTSxJQUFJLE1BQU0sMEJBQTBCO0FBQUEsUUFDNUM7QUFBQSxNQUNGO0FBY0EsTUFBTSxPQUFpQixDQUFDLFVBQVUsQ0FBQyxJQUFJLElBQUksZUFBZSxNQUFNLGFBQWEsZUFBZSxDQUFDLEtBQUssRUFBRTtBQUM3RixNQUFNLDBCQUEwQixDQUNyQyxNQUNBLGFBQ0EsUUFDQSxVQUNBLFdBQ0EsZ0JBQ0EsV0FBVyxPQUNYLG9CQUFvQixVQUNKO0FBQ2hCLGNBQU0sY0FBd0IsQ0FBQztBQUMvQixjQUFNLGFBQWEsT0FBTyxDQUFDLEVBQUU7QUFDN0IsY0FBTSxZQUFZLFdBQVc7QUFDN0IsY0FBTSxPQUFPLFVBQVUsY0FBYyxXQUFXLFNBQVM7QUFDekQsY0FBTSxrQkFBa0IsQ0FBQyxxQkFBcUIsS0FBSyxXQUFXO0FBQzlELG1CQUFXLFFBQVEsQ0FBQyxHQUFHLE1BQU07QUFDM0IsY0FBSSxtQkFBbUIsS0FBSyxRQUFRLENBQUMsS0FBSyxHQUFHO0FBQzNDLGdCQUFJLFVBQVU7QUFDWiwwQkFBWSxLQUFLLENBQUM7QUFBQSxZQUNwQjtBQUFBLFVBQ0YsT0FBTztBQUNMLHdCQUFZLEtBQUssQ0FBQztBQUFBLFVBQ3BCO0FBQUEsUUFDRixDQUFDO0FBQ0QsY0FBTSxhQUFhLFlBQVk7QUFDL0IsY0FBTSxhQUFhLFVBQVUsS0FBSyxXQUFXO0FBQzdDLGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQ3RELGdCQUFNLFVBQW9CLENBQUM7QUFFM0IsZ0JBQU0sUUFBUSxjQUFjLE1BQU0sT0FBTyxDQUFDLEVBQUUsVUFBVSxTQUFTO0FBQy9ELGdCQUFNLFNBQVMsZUFBZSxVQUFVLGdCQUFnQixVQUFVO0FBQ2xFLGdCQUFNLE1BQU0sU0FBUyxPQUFPLFFBQVEsSUFBSTtBQUN4QyxjQUFJQyxhQUFZLElBQUksQ0FBQztBQUVyQixtQkFBUyxJQUFJLEdBQUcsSUFBSSxHQUFHLElBQUksV0FBVyxLQUFLO0FBRXpDLGdCQUFJLG1CQUFtQixLQUFLLFFBQVEsQ0FBQyxLQUFLLEdBQUc7QUFDM0Msa0JBQUksVUFBVTtBQUNaO0FBQUEsY0FDRjtBQUVBLGNBQUFBLGFBQVksWUFBWSxDQUFDLGVBQWUsQ0FBQyxNQUFNLFdBQVcsQ0FBQyxDQUFDLE1BQU0sQ0FBQztBQUFBLG9CQUN2RCxJQUFJLENBQUMsRUFBRSxTQUFTLFlBQVksSUFBSSxxQkFBcUIsQ0FBQyxNQUFNLEVBQUU7QUFBQSxvQkFDOUQsTUFBTSxXQUFXLGlCQUFpQixHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7QUFBQSxvQkFDN0NBLFVBQVM7QUFBQTtBQUFBLFlBRXZCLE9BQU87QUFDTCxzQkFBUSxLQUFLLEdBQUcsTUFBTSxXQUFXLGlCQUFpQixHQUFHLE9BQU8sV0FBVyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsR0FBRztBQUMvRjtBQUFBLFlBQ0Y7QUFBQSxVQUNGO0FBQ0EsaUJBQU87QUFBQTtBQUFBLFVBRUQsYUFBYSxnQkFBZ0IsZUFBZSxLQUFLLEVBQUUsaUJBQWlCLE9BQU8sTUFBTSxDQUFDO0FBQUE7QUFBQSxVQUVsRixhQUFhLFVBQVUsQ0FBQztBQUFBLFlBQ3RCLGFBQWEsc0NBQXNDLHNCQUFzQixDQUFDO0FBQUEsK0JBQ3ZELE1BQU0sS0FBSyxPQUFPO0FBQUEsaUNBQ2hCLE9BQU8sZ0JBQWdCLFlBQVksQ0FBQztBQUFBO0FBQUEsWUFFekQsUUFBUSxLQUFLLElBQUksQ0FBQztBQUFBLFlBQ2xCLElBQUksQ0FBQyxDQUFDO0FBQUEsWUFDTixJQUFJLENBQUMsQ0FBQztBQUFBLFlBQ05BLFVBQVM7QUFBQSxZQUNULElBQUksQ0FBQyxDQUFDO0FBQUEsWUFDTixJQUFJLFdBQVcsSUFBSSxPQUFPLFlBQVksY0FBYyxPQUFPLElBQUksSUFBSSxNQUFNLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQztBQUFBO0FBQUEsUUFFaEc7QUFFQSxlQUFPO0FBQUEsVUFDTDtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQSxZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxlQUFlLENBQUM7QUFBQSxZQUN6RCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxhQUFhO0FBQUE7QUFBQSxZQUF1QixFQUFFO0FBQUEsWUFDcEUsaUJBQWlCO0FBQUEsY0FDZixFQUFFLHVCQUF1QixNQUFNLFdBQVc7QUFBQSxjQUMxQyxHQUFHLDJCQUEyQixZQUFZLFdBQVc7QUFBQSxZQUN2RDtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sbUNBQW1DLENBQzlDLFFBQ0EsZUFDcUI7QUFDckIsY0FBTSxPQUFpQixDQUFDO0FBQ3hCLFlBQUksT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLElBQUksR0FBRztBQUN6QixpQkFBTyxDQUFDLEVBQUUsaUJBQWlCLEVBQUUsUUFBUSxDQUFDLE1BQU0sS0FBSyxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFBQSxRQUNsRTtBQUNBLGVBQU8sNEJBQTRCO0FBQUEsVUFDakM7QUFBQSxVQUNBLFVBQVUsV0FBVztBQUFBLFVBQ3JCLG1CQUFtQixXQUFXO0FBQUEsUUFDaEMsQ0FBQztBQUFBLE1BQ0g7QUFFQSxNQUFNLG1CQUFtQixDQUN2QixTQUNBLE1BQ0EsWUFDQSxhQUNTO0FBQ1QsY0FBTSxTQUFTLFFBQVE7QUFDdkIsY0FBTSxvQkFDSixPQUFPLFdBQVcsSUFBSSxhQUFhLGlDQUFpQyxRQUFRLFVBQVU7QUFFeEYsZ0JBQVE7QUFBQSxVQUNOO0FBQUEsWUFDRTtBQUFBLFlBQ0EsRUFBRSxNQUFNLGtCQUFrQixVQUFVLG1CQUFtQixDQUFDLE1BQU0sRUFBRTtBQUFBLFlBQ2hFLENBQUMsT0FBTyxDQUFDLENBQUM7QUFBQSxZQUNWLGtCQUFrQixxQkFBcUIsa0JBQWtCLEtBQUssV0FBVyxJQUFJLE9BQU87QUFBQSxZQUNwRixrQkFBa0I7QUFBQSxZQUNsQixPQUFPLENBQUMsRUFBRTtBQUFBLFlBQ1Ysa0JBQWtCO0FBQUEsWUFDbEIsa0JBQWtCO0FBQUEsVUFDcEI7QUFBQSxVQUNBLEVBQUUsUUFBUSxDQUFDLENBQUMsRUFBRTtBQUFBLFFBQ2hCO0FBQUEsTUFDRjtBQUVBLE1BQU0sb0JBQW9CLENBQUMsU0FBeUIsZUFBdUM7QUFDekYsUUFBQUQsZ0JBQWUsUUFBUSxNQUFNO0FBQzdCLGNBQU0sV0FBcUIsQ0FBQyxPQUFPLFdBQVc7QUFBQSxVQUM1QyxlQUFlLE9BQU8sS0FBSyxPQUFPO0FBQUEsVUFDbEM7QUFBQSxVQUNBLFlBQVksTUFBTSxhQUFhLGVBQWUsQ0FBQztBQUFBLFVBQy9DO0FBQUEsUUFDRjtBQUNBLHlCQUFpQixTQUFTLGdCQUFnQixZQUFZLFFBQVE7QUFBQSxNQUNoRTtBQUVBLE1BQU0sZ0JBQWdCLENBQUMsU0FBeUIsZUFBdUM7QUFDckYsUUFBQUEsZ0JBQWUsUUFBUSxNQUFNO0FBQzdCLGNBQU0sV0FBcUIsQ0FBQyxPQUFPLFdBQVc7QUFBQSxVQUM1QyxlQUFlLE9BQU8sS0FBSyxPQUFPO0FBQUEsVUFDbEM7QUFBQSxVQUNBLGdCQUFnQixNQUFNLGFBQWEsZUFBZSxDQUFDO0FBQUEsVUFDbkQ7QUFBQSxRQUNGO0FBQ0EseUJBQWlCLFNBQVMsWUFBWSxZQUFZLFFBQVE7QUFBQSxNQUM1RDtBQUVBLE1BQU0sZ0JBQWdCLENBQUMsU0FBeUIsZUFBdUM7QUFDckYsUUFBQUEsZ0JBQWUsUUFBUSxNQUFNO0FBQzdCLGNBQU0sV0FBcUIsQ0FBQyxPQUFPLFdBQVc7QUFBQSxVQUM1QyxXQUFXLE9BQU8sS0FBSyxLQUFLLG9CQUFvQixPQUFPLEtBQUssS0FBSztBQUFBLFVBQ2pFO0FBQUEsVUFDQSxPQUFPLE1BQU0sYUFBYSxlQUFlLENBQUM7QUFBQSxVQUMxQztBQUFBLFFBQ0Y7QUFDQSx5QkFBaUIsU0FBUyxZQUFZLFlBQVksUUFBUTtBQUFBLE1BQzVEO0FBRUEsTUFBTSx1QkFBdUIsQ0FBQyxTQUF5QixlQUF1QztBQUM1RixRQUFBQSxnQkFBZSxRQUFRLE1BQU07QUFDN0IsY0FBTSxXQUFxQixDQUFDLE9BQU8sV0FBVztBQUFBLFVBQzVDLGVBQWUsT0FBTyxLQUFLLE9BQU87QUFBQSxVQUNsQztBQUFBLFVBQ0EsZ0JBQWdCLE1BQU0sYUFBYSxlQUFlLENBQUM7QUFBQSxVQUNuRDtBQUFBLFFBQ0Y7QUFDQSx5QkFBaUIsU0FBUyxtQkFBbUIsWUFBWSxRQUFRO0FBQUEsTUFDbkU7QUFFQSxNQUFNLGlCQUFpQixDQUFDLFNBQXlCLGVBQXVDO0FBQ3RGLFFBQUFBLGdCQUFlLFFBQVEsTUFBTTtBQUM3QixjQUFNLFdBQXFCLENBQUMsT0FBTyxTQUFTLFNBQVM7QUFDbkQsZ0JBQU0sVUFBVSxDQUFDO0FBQ2pCLG1CQUFTLElBQUksR0FBRyxJQUFJLE1BQU0sTUFBTSxLQUFLO0FBQ25DLGdCQUFJLEtBQUssUUFBUSxDQUFDLEtBQUssS0FBSyxLQUFLLFdBQVcsR0FBRztBQUM3QyxzQkFBUSxLQUFLLE1BQU0sV0FBVyxpQkFBaUIsR0FBRyxDQUFDLENBQUM7QUFBQSxZQUN0RDtBQUFBLFVBQ0Y7QUFFQSxpQkFBTztBQUFBLFlBQ0wsR0FBRyxRQUFRLEtBQUssSUFBSSxDQUFDO0FBQUEsWUFDckIsZUFBZSxNQUFNLGFBQWEsZUFBZSxDQUFDO0FBQUEsWUFDbEQsc0JBQXNCLE1BQU0sYUFBYSxlQUFlLENBQUM7QUFBQSxZQUN6RDtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQ0EseUJBQWlCLFNBQVMsYUFBYSxZQUFZLFFBQVE7QUFBQSxNQUM3RDtBQUVBLE1BQU0sa0JBQWtCLENBQUMsU0FBeUIsZUFBdUM7QUFDdkYsUUFBQUEsZ0JBQWUsUUFBUSxNQUFNO0FBQzdCLGNBQU0sV0FBcUIsQ0FBQyxPQUFPLFFBQVEsU0FBUztBQUNsRCxjQUFJLE9BQU87QUFDWCxtQkFBUyxJQUFJLEdBQUcsSUFBSSxNQUFNLE1BQU0sS0FBSztBQUNuQyxnQkFBSSxLQUFLLFFBQVEsQ0FBQyxLQUFLLEtBQUssS0FBSyxXQUFXLEdBQUc7QUFFN0Msc0JBQVEsUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUM7QUFBQSxZQUNsQztBQUFBLFVBQ0Y7QUFFQSxpQkFBTztBQUFBLFlBQ0w7QUFBQSxZQUNBO0FBQUEsWUFDQSxjQUFjLE1BQU0sYUFBYSxlQUFlLENBQUM7QUFBQSxZQUNqRCxlQUFlLE9BQU8sS0FBSyxLQUFLLFVBQVUsSUFBSTtBQUFBLFVBQ2hEO0FBQUEsUUFDRjtBQUNBLHlCQUFpQixTQUFTLGNBQWMsWUFBWSxRQUFRO0FBQUEsTUFDOUQ7QUFFQSxNQUFNLGlCQUFpQixDQUFDLFNBQXlCLGVBQXVDO0FBQ3RGLFFBQUFBLGdCQUFlLFFBQVEsTUFBTTtBQUM3QixjQUFNLFdBQXFCLENBQUMsT0FBTyxTQUFTLFNBQVM7QUFDbkQsZ0JBQU0sVUFBVSxDQUFDO0FBQ2pCLG1CQUFTLElBQUksR0FBRyxJQUFJLE1BQU0sTUFBTSxLQUFLO0FBQ25DLGdCQUFJLEtBQUssUUFBUSxDQUFDLEtBQUssS0FBSyxLQUFLLFdBQVcsR0FBRztBQUM3QyxzQkFBUSxLQUFLLGlCQUFpQixDQUFDLFFBQVE7QUFBQSxZQUN6QztBQUFBLFVBQ0Y7QUFFQSxpQkFBTztBQUFBLFlBQ0wsR0FBRyxRQUFRLEtBQUssSUFBSSxDQUFDO0FBQUEsWUFDckIsZUFBZSxNQUFNLGFBQWEsZUFBZSxDQUFDO0FBQUEsWUFDbEQsc0JBQXNCLE1BQU0sYUFBYSxlQUFlLENBQUM7QUFBQSxZQUN6RDtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQ0EseUJBQWlCLFNBQVMsYUFBYSxZQUFZLFFBQVE7QUFBQSxNQUM3RDtBQUVBLE1BQU0sa0JBQWtCLENBQUMsU0FBeUIsZUFBdUM7QUFDdkYsUUFBQUEsZ0JBQWUsUUFBUSxNQUFNO0FBQzdCLGNBQU0sV0FBcUIsQ0FBQyxPQUFPLFdBQVc7QUFBQSxVQUM1QyxlQUFlLE9BQU8sS0FBSyxPQUFPO0FBQUEsVUFDbEM7QUFBQSxVQUNBLFlBQVksTUFBTSxhQUFhLGVBQWUsQ0FBQztBQUFBLFVBQy9DO0FBQUEsUUFDRjtBQUNBLHlCQUFpQixTQUFTLGNBQWMsWUFBWSxRQUFRO0FBQUEsTUFDOUQ7QUFFQSxNQUFNLGlCQUFpQixDQUFDLFNBQXlCLGVBQXVDO0FBQ3RGLFFBQUFBLGdCQUFlLFFBQVEsTUFBTTtBQUM3QixjQUFNLFdBQXFCLENBQUMsT0FBTyxXQUFXO0FBQUEsVUFDNUMsZUFBZSxPQUFPLEtBQUssT0FBTztBQUFBLFVBQ2xDO0FBQUEsVUFDQSxZQUFZLE1BQU0sYUFBYSxlQUFlLENBQUM7QUFBQSxVQUMvQztBQUFBLFFBQ0Y7QUFDQSx5QkFBaUIsU0FBUyxhQUFhLFlBQVksUUFBUTtBQUFBLE1BQzdEO0FBRUEsTUFBTSx1QkFBdUIsQ0FBQyxTQUF5QixlQUF1QztBQUM1RixRQUFBQSxnQkFBZSxRQUFRLE1BQU07QUFDN0IsY0FBTSxXQUFxQixDQUFDLE9BQU8sV0FBVztBQUFBLFVBQzVDLFdBQVcsT0FBTyxLQUFLLEtBQUssb0JBQW9CLE9BQU8sS0FBSyxLQUFLO0FBQUEsVUFDakU7QUFBQSxVQUNBLE9BQU8sTUFBTSxhQUFhLGVBQWUsQ0FBQztBQUFBLFVBQzFDO0FBQUEsUUFDRjtBQUNBLHlCQUFpQixTQUFTLG1CQUFtQixZQUFZLFFBQVE7QUFBQSxNQUNuRTtBQUVBLE1BQU0sdUJBQXVCLENBQzNCLE9BQ0EsTUFDQSxzQkFDWTtBQUNaLFlBQUksS0FBSyxXQUFXLEdBQUc7QUFDckIsaUJBQU87QUFBQSxRQUNUO0FBRUEsWUFBSSxhQUFhO0FBQ2pCLFlBQUksYUFBYTtBQUNqQixpQkFBUyxNQUFNLEdBQUcsTUFBTSxLQUFLLFFBQVEsT0FBTztBQUMxQyxjQUFJLEtBQUssUUFBUSxHQUFHLE1BQU0sSUFBSTtBQUM1QiwwQkFBYyxNQUFNLEdBQUc7QUFBQSxVQUN6QixPQUFPO0FBQ0wsMEJBQWMsTUFBTSxHQUFHO0FBQUEsVUFDekI7QUFBQSxRQUNGO0FBS0EsZUFBTyxhQUFhLE1BQU0sYUFBYTtBQUFBLE1BQ3pDO0FBRU8sTUFBTSxhQUFhLENBQUMsU0FBeUIsZUFBdUM7QUFDekYsWUFBSSxxQkFBcUIsUUFBUSxPQUFPLENBQUMsRUFBRSxNQUFNLFdBQVcsTUFBTSxXQUFXLGlCQUFpQixHQUFHO0FBQy9GLDBCQUFnQixTQUFTLFVBQVU7QUFBQSxRQUNyQyxPQUFPO0FBQ0wsMkJBQWlCLFNBQVMsVUFBVTtBQUFBLFFBQ3RDO0FBQUEsTUFDRjtBQUVPLE1BQU0sV0FBVyxDQUFDLFNBQXlCLGVBQXVDO0FBQ3ZGLFlBQUkscUJBQXFCLFFBQVEsT0FBTyxDQUFDLEVBQUUsTUFBTSxXQUFXLE1BQU0sV0FBVyxpQkFBaUIsR0FBRztBQUMvRix3QkFBYyxTQUFTLFVBQVU7QUFBQSxRQUNuQyxPQUFPO0FBQ0wseUJBQWUsU0FBUyxVQUFVO0FBQUEsUUFDcEM7QUFBQSxNQUNGO0FBRU8sTUFBTSxXQUFXLENBQUMsU0FBeUIsZUFBdUM7QUFDdkYsWUFBSSxxQkFBcUIsUUFBUSxPQUFPLENBQUMsRUFBRSxNQUFNLFdBQVcsTUFBTSxXQUFXLGlCQUFpQixHQUFHO0FBQy9GLHdCQUFjLFNBQVMsVUFBVTtBQUFBLFFBQ25DLE9BQU87QUFDTCx5QkFBZSxTQUFTLFVBQVU7QUFBQSxRQUNwQztBQUFBLE1BQ0Y7QUFFTyxNQUFNLGtCQUFrQixDQUFDLFNBQXlCLGVBQXVDO0FBQzlGLFlBQUkscUJBQXFCLFFBQVEsT0FBTyxDQUFDLEVBQUUsTUFBTSxXQUFXLE1BQU0sV0FBVyxpQkFBaUIsR0FBRztBQUMvRiwrQkFBcUIsU0FBUyxVQUFVO0FBQUEsUUFDMUMsT0FBTztBQUNMLGdDQUFzQixTQUFTLFVBQVU7QUFBQSxRQUMzQztBQUFBLE1BQ0Y7QUFFTyxNQUFNLFlBQVksQ0FBQyxTQUF5QixlQUF1QztBQUN4RixZQUFJLHFCQUFxQixRQUFRLE9BQU8sQ0FBQyxFQUFFLE1BQU0sV0FBVyxNQUFNLFdBQVcsaUJBQWlCLEdBQUc7QUFDL0YseUJBQWUsU0FBUyxVQUFVO0FBQUEsUUFDcEMsT0FBTztBQUNMLDBCQUFnQixTQUFTLFVBQVU7QUFBQSxRQUNyQztBQUFBLE1BQ0Y7QUFFTyxNQUFNLFlBQVksQ0FBQyxTQUF5QixlQUF1QztBQUN4RixZQUFJLHFCQUFxQixRQUFRLE9BQU8sQ0FBQyxFQUFFLE1BQU0sV0FBVyxNQUFNLFdBQVcsaUJBQWlCLEdBQUc7QUFDL0YseUJBQWUsU0FBUyxVQUFVO0FBQUEsUUFDcEMsT0FBTztBQUNMLDBCQUFnQixTQUFTLFVBQVU7QUFBQSxRQUNyQztBQUFBLE1BQ0Y7QUFFTyxNQUFNLGFBQWEsQ0FBQyxTQUF5QixlQUF1QztBQUN6RixZQUFJLHFCQUFxQixRQUFRLE9BQU8sQ0FBQyxFQUFFLE1BQU0sV0FBVyxNQUFNLFdBQVcsaUJBQWlCLEdBQUc7QUFDL0YsMEJBQWdCLFNBQVMsVUFBVTtBQUFBLFFBQ3JDLE9BQU87QUFDTCwyQkFBaUIsU0FBUyxVQUFVO0FBQUEsUUFDdEM7QUFBQSxNQUNGO0FBRU8sTUFBTSxZQUFZLENBQUMsU0FBeUIsZUFBdUM7QUFDeEYsWUFBSSxxQkFBcUIsUUFBUSxPQUFPLENBQUMsRUFBRSxNQUFNLFdBQVcsTUFBTSxXQUFXLGlCQUFpQixHQUFHO0FBQy9GLHlCQUFlLFNBQVMsVUFBVTtBQUFBLFFBQ3BDLE9BQU87QUFDTCwwQkFBZ0IsU0FBUyxVQUFVO0FBQUEsUUFDckM7QUFBQSxNQUNGO0FBRU8sTUFBTSxrQkFBa0IsQ0FBQyxTQUF5QixlQUF1QztBQUM5RixZQUFJLHFCQUFxQixRQUFRLE9BQU8sQ0FBQyxFQUFFLE1BQU0sV0FBVyxNQUFNLFdBQVcsaUJBQWlCLEdBQUc7QUFDL0YsK0JBQXFCLFNBQVMsVUFBVTtBQUFBLFFBQzFDLE9BQU87QUFDTCxnQ0FBc0IsU0FBUyxVQUFVO0FBQUEsUUFDM0M7QUFBQSxNQUNGO0FBRU8sTUFBTSxlQUFlLENBQUMsU0FBeUIsZUFBdUM7QUFDM0YsWUFBSSxxQkFBcUIsUUFBUSxPQUFPLENBQUMsRUFBRSxNQUFNLFdBQVcsTUFBTSxXQUFXLGlCQUFpQixHQUFHO0FBQy9GLDRCQUFrQixTQUFTLFVBQVU7QUFBQSxRQUN2QyxPQUFPO0FBQ0wsNkJBQW1CLFNBQVMsVUFBVTtBQUFBLFFBQ3hDO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQzNaQSxNQWNNRSxpQkFlTyxRQW1DQSxRQW1DQTtBQW5HYjtBQUFBO0FBQUE7QUFPQTtBQUVBO0FBR0E7QUFFQSxNQUFNQSxrQkFBaUIsQ0FBQyxXQUF3QztBQUM5RCxZQUFJLENBQUMsVUFBVSxPQUFPLFdBQVcsS0FBSyxPQUFPLFNBQVMsR0FBRztBQUN2RCxnQkFBTSxJQUFJLE1BQU0sd0NBQXdDO0FBQUEsUUFDMUQ7QUFDQSxZQUFJLE9BQU8sQ0FBQyxFQUFFLDRCQUE2QjtBQUN6QyxnQkFBTSxJQUFJLE1BQU0scUJBQXFCO0FBQUEsUUFDdkM7QUFBQSxNQUNGO0FBUU8sTUFBTSxTQUFTLENBQUMsU0FBeUIsZUFBMEM7QUFDeEYsUUFBQUEsZ0JBQWUsUUFBUSxNQUFNO0FBQzdCLGNBQU0sY0FBd0IsQ0FBQyxPQUFPLFFBQVEsU0FBUztBQUNyRCxnQkFBTSxVQUFVLENBQUM7QUFDakIsbUJBQVMsSUFBSSxHQUFHLElBQUksTUFBTSxNQUFNLEtBQUs7QUFDbkMsZ0JBQUksS0FBSyxRQUFRLENBQUMsS0FBSyxLQUFLLEtBQUssV0FBVyxHQUFHO0FBQzdDLHNCQUFRLEtBQUssaUJBQWlCLENBQUMsUUFBUTtBQUFBLFlBQ3pDO0FBQUEsVUFDRjtBQUNBLGlCQUFPO0FBQUEsWUFDTCxHQUFHLFFBQVEsS0FBSyxJQUFJLENBQUM7QUFBQSxZQUNyQixlQUFlLE1BQU0sYUFBYSxlQUFlLENBQUM7QUFBQTtBQUFBLFlBQ2xELE9BQU8sTUFBTSxhQUFhLGVBQWUsQ0FBQyxJQUFJLFdBQVcsa0JBQWtCLElBQUksT0FBTyxHQUFHO0FBQUEsbUJBQzVFLE1BQU0sYUFBYSxlQUFlLENBQUM7QUFBQTtBQUFBO0FBQUEsWUFHaEQ7QUFBQSxZQUNBLE9BQU8sWUFBWSxjQUFjLFlBQVk7QUFBQSxVQUMvQztBQUFBLFFBQ0Y7QUFFQSxnQkFBUTtBQUFBLFVBQ047QUFBQSxZQUNFO0FBQUEsWUFDQSxFQUFFLE1BQU0sV0FBVyxVQUFVLG1CQUFtQixDQUFDLE1BQU0sRUFBRTtBQUFBLFlBQ3pELENBQUMsUUFBUSxPQUFPLENBQUMsQ0FBQztBQUFBLFlBQ2xCO0FBQUEsWUFDQSxDQUFDLFdBQVcsSUFBSTtBQUFBO0FBQUEsWUFFaEIsV0FBVztBQUFBLFVBQ2I7QUFBQSxVQUNBLEVBQUUsUUFBUSxDQUFDLENBQUMsRUFBRTtBQUFBLFFBQ2hCO0FBQUEsTUFDRjtBQUVPLE1BQU0sU0FBUyxDQUFDLFNBQXlCLGVBQTBDO0FBQ3hGLFFBQUFBLGdCQUFlLFFBQVEsTUFBTTtBQUM3QixjQUFNLGNBQXdCLENBQUMsT0FBTyxRQUFRLFNBQVM7QUFDckQsZ0JBQU0sVUFBVSxDQUFDO0FBQ2pCLG1CQUFTLElBQUksR0FBRyxJQUFJLE1BQU0sTUFBTSxLQUFLO0FBQ25DLGdCQUFJLEtBQUssUUFBUSxDQUFDLEtBQUssS0FBSyxLQUFLLFdBQVcsR0FBRztBQUM3QyxzQkFBUSxLQUFLLGlCQUFpQixDQUFDLFFBQVE7QUFBQSxZQUN6QztBQUFBLFVBQ0Y7QUFDQSxpQkFBTztBQUFBLFlBQ0wsR0FBRyxRQUFRLEtBQUssSUFBSSxDQUFDO0FBQUEsWUFDckIsZUFBZSxNQUFNLGFBQWEsZUFBZSxDQUFDO0FBQUE7QUFBQSxZQUNsRCxPQUFPLE1BQU0sYUFBYSxlQUFlLENBQUMsSUFBSSxXQUFXLGtCQUFrQixJQUFJLE9BQU8sR0FBRztBQUFBLG1CQUM1RSxNQUFNLGFBQWEsZUFBZSxDQUFDO0FBQUE7QUFBQTtBQUFBLFlBR2hEO0FBQUEsWUFDQSxPQUFPLFlBQVksY0FBYyxZQUFZO0FBQUEsVUFDL0M7QUFBQSxRQUNGO0FBRUEsZ0JBQVE7QUFBQSxVQUNOO0FBQUEsWUFDRTtBQUFBLFlBQ0EsRUFBRSxNQUFNLFdBQVcsVUFBVSxtQkFBbUIsQ0FBQyxNQUFNLEVBQUU7QUFBQSxZQUN6RCxDQUFDLFFBQVEsT0FBTyxDQUFDLENBQUM7QUFBQSxZQUNsQjtBQUFBLFlBQ0EsQ0FBQyxXQUFXLElBQUk7QUFBQTtBQUFBLFlBRWhCLFdBQVc7QUFBQSxVQUNiO0FBQUEsVUFDQSxFQUFFLFFBQVEsQ0FBQyxDQUFDLEVBQUU7QUFBQSxRQUNoQjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLDJCQUEyQixDQUFDLGVBQ3ZDLDRCQUE0QixVQUFvRTtBQUFBO0FBQUE7OztBQ3BHbEcsTUFxRk0seUJBbUxBLGFBMEJBLGlDQXVKQSxpQ0FnTUEsbUNBa0tPLGdCQThGUCxTQXFITztBQTkrQmI7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUNBO0FBRUE7QUE2RUEsTUFBTSwwQkFBMEIsQ0FBQyxRQUErQixlQUFvRDtBQW1DbEgsY0FBTSxRQUFRLE9BQU8sQ0FBQztBQUN0QixjQUFNLFVBQVUsT0FBTyxDQUFDO0FBQ3hCLGNBQU0sT0FBTyxPQUFPLENBQUM7QUFDckIsY0FBTSxZQUFZLE9BQU8sQ0FBQztBQUMxQixjQUFNLE9BQU8sT0FBTyxDQUFDO0FBQ3JCLGNBQU0sZ0JBQWdCLE9BQU8sQ0FBQztBQUU5QixZQUFJLFFBQVEsZUFBZTtBQUN6QixnQkFBTSxJQUFJLE1BQU0sb0RBQW9EO0FBQUEsUUFDdEU7QUFFQSxZQUFJLE1BQU0sS0FBSyxXQUFXLEdBQUc7QUFDM0IsZ0JBQU0sSUFBSSxNQUFNLHNDQUFzQztBQUFBLFFBQ3hEO0FBRUEsY0FBTSxZQUFZLE1BQU0sS0FBSyxDQUFDO0FBQzlCLGNBQU0saUJBQWlCLE1BQU0sS0FBSyxDQUFDO0FBQ25DLGNBQU0sa0JBQWtCLE1BQU0sS0FBSyxDQUFDO0FBRXBDLFlBQUksS0FBSyxLQUFLLFdBQVcsR0FBRztBQUMxQixnQkFBTSxJQUFJLE1BQU0sK0NBQStDO0FBQUEsUUFDakU7QUFFQSxZQUFJLFFBQVEsS0FBSyxXQUFXLEdBQUc7QUFDN0IsZ0JBQU0sSUFBSSxNQUFNLGtEQUFrRDtBQUFBLFFBQ3BFO0FBRUEsWUFBSSxRQUFRLEtBQUssQ0FBQyxNQUFNLGlCQUFpQjtBQUN2QyxnQkFBTSxJQUFJLE1BQU0sdUVBQXVFO0FBQUEsUUFDekY7QUFFQSxZQUFJLEtBQUssS0FBSyxDQUFDLE1BQU0sUUFBUSxLQUFLLENBQUMsR0FBRztBQUNwQyxnQkFBTSxJQUFJLE1BQU0sb0ZBQW9GO0FBQUEsUUFDdEc7QUFFQSxZQUFJLGNBQWMsS0FBSyxLQUFLLENBQUMsSUFBSTtBQUNqQyxZQUFJLGNBQWM7QUFDbEIsWUFBSSxjQUFjO0FBQ2xCLFlBQUksV0FBVyxlQUFlLFNBQVMsR0FBRztBQUN4QyxjQUFJLFdBQVcsZUFBZSxXQUFXLEdBQUc7QUFDMUMsa0JBQU0sSUFBSSxNQUFNLG1EQUFtRDtBQUFBLFVBQ3JFO0FBQ0EscUJBQVcsTUFBTSxXQUFXLGdCQUFnQjtBQUMxQyxnQkFBSSxLQUFLLFdBQVcsYUFBYSxHQUFHO0FBQ2xDLG9CQUFNLElBQUksTUFBTSxtREFBbUQ7QUFBQSxZQUNyRTtBQUFBLFVBQ0Y7QUFFQSx3QkFBYyxXQUFXLGVBQWUsQ0FBQztBQUN6Qyx3QkFBYyxXQUFXLGVBQWUsQ0FBQztBQUN6Qyx3QkFBYyxXQUFXLGVBQWUsQ0FBQztBQUFBLFFBQzNDO0FBRUEsY0FBTSxtQkFBbUI7QUFFekIsWUFBSSxnQkFBZ0IsYUFBYTtBQUMvQixnQkFBTSxJQUFJLE1BQU0sNkRBQTZEO0FBQUEsUUFDL0U7QUFFQSxZQUFJLEtBQUssS0FBSyxDQUFDLE1BQU0sY0FBYyxjQUFjLGFBQWE7QUFDNUQsZ0JBQU0sSUFBSSxNQUFNLCtFQUErRTtBQUFBLFFBQ2pHO0FBRUEsWUFBSSxxQkFBcUI7QUFDekIsWUFBSSxNQUFNO0FBQ1IsY0FBSSxnQkFBZ0IsYUFBYTtBQUMvQixrQkFBTSxJQUFJLE1BQU0sb0RBQW9EO0FBQUEsVUFDdEU7QUFDQSxjQUFJLEtBQUssS0FBSyxXQUFXLEdBQUc7QUFDMUIsa0JBQU0sSUFBSSxNQUFNLHFDQUFxQztBQUFBLFVBQ3ZEO0FBQ0EsY0FBSSxLQUFLLEtBQUssQ0FBQyxNQUFNLEdBQUc7QUFDdEIsa0JBQU0sSUFBSSxNQUFNLHdDQUF3QztBQUFBLFVBQzFEO0FBQ0EsY0FBSSxLQUFLLEtBQUssQ0FBQyxNQUFNLFdBQVc7QUFDOUIsa0JBQU0sSUFBSSxNQUFNLGtEQUFrRDtBQUFBLFVBQ3BFO0FBQ0EsY0FBSSxLQUFLLEtBQUssQ0FBQyxNQUFNLFdBQVcsVUFBVTtBQUN4QyxrQkFBTSxJQUFJLE1BQU0sZ0RBQWdEO0FBQUEsVUFDbEU7QUFDQSxjQUFJLEtBQUssS0FBSyxDQUFDLE1BQU0sY0FBYyxXQUFXLFVBQVU7QUFDdEQsa0JBQU0sSUFBSSxNQUFNLGdFQUFnRTtBQUFBLFVBQ2xGO0FBRUEsY0FBSSxDQUFDLFdBQVcsd0JBQXdCO0FBQ3RDLGlDQUFxQixLQUFLLEtBQUssQ0FBQztBQUFBLFVBQ2xDO0FBQUEsUUFFRjtBQUVBLGNBQU0sc0JBQXNCLG1CQUFtQjtBQUMvQyxjQUFNLG9CQUFvQjtBQUUxQixjQUFNLFdBQVc7QUFDakIsWUFBSSxXQUFXO0FBR2IsZ0JBQU0sSUFBSSxNQUFNLG9CQUFvQjtBQUFBLFFBQ3RDO0FBRUEsWUFBSSxNQUFNO0FBQ1IsZ0JBQU0sSUFBSSxNQUFNLHVCQUF1QjtBQUFBLFFBQ3pDO0FBRUEsWUFBSSxlQUFlO0FBQ2pCLGNBQUksY0FBYyxLQUFLLFdBQVcsR0FBRztBQUNuQyxrQkFBTSxJQUFJLE1BQU0sK0NBQStDO0FBQUEsVUFDakU7QUFHQSxjQUNFLGNBQWMsS0FBSyxDQUFDLE1BQU0sYUFDMUIsY0FBYyxLQUFLLENBQUMsTUFBTSxXQUFXLFlBQ3JDLGNBQWMsS0FBSyxDQUFDLE1BQU0sa0JBQzFCLGNBQWMsS0FBSyxDQUFDLE1BQU0scUJBQzFCO0FBQ0Esa0JBQU0sSUFBSSxNQUFNLCtGQUErRjtBQUFBLFVBQ2pIO0FBQUEsUUFDRjtBQUVBLGVBQU87QUFBQSxVQUNMO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQSxZQUFZO0FBQUEsVUFDWjtBQUFBLFVBQ0EsVUFBVSxLQUFLLE1BQU0sY0FBYyxXQUFXLFFBQVE7QUFBQSxVQUN0RCxXQUFXLEtBQUssTUFBTSxjQUFjLFdBQVcsUUFBUTtBQUFBLFVBQ3ZELFVBQVUsV0FBVztBQUFBLFVBQ3JCLGtCQUFrQjtBQUFBLFVBQ2xCLHdCQUF3QjtBQUFBLFVBQ3hCLGlCQUFpQixXQUFXO0FBQUEsVUFDNUI7QUFBQSxVQUNBLE9BQU8sV0FBVztBQUFBLFVBQ2xCLHFCQUFxQjtBQUFBLFVBQ3JCLGNBQWM7QUFBQSxVQUNkLFdBQVc7QUFBQSxRQUNiO0FBQUEsTUFDRjtBQUVBLE1BQU0sY0FBYyxDQUNsQixjQUNBLDBCQUNBLDJCQUNHO0FBRUgsWUFBSSw0QkFBNEIsY0FBYztBQUM1QyxpQkFBTztBQUFBLDhDQUNtQyx5QkFBeUIsWUFBWSxHQUFHLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQ0FJbkQsY0FBYyxZQUFZLFVBQVUsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxRQU12RSxPQUFPO0FBQ0wsaUJBQU87QUFBQSxNQUNMLHlCQUF5Qiw2REFBNkQsRUFBRTtBQUFBO0FBQUE7QUFBQSxRQUc1RjtBQUFBLE1BQ0Y7QUFFQSxNQUFNLGtDQUFrQyxDQUN0QyxPQUNBLFdBQ0EsVUFDQSxvQkFDQSxnQkFDQSxxQkFDQSxTQUNBLDZCQUNHO0FBRUgsY0FBTSxhQUFhLGlCQUFpQixVQUFVLElBQUksbUJBQW1CO0FBQ3JFLFlBQUksS0FBSztBQUNULGNBQU0sMEJBQTBCLHNCQUFzQjtBQUN0RCxZQUFJLDBCQUEwQixJQUFJO0FBQ2hDLGVBQUs7QUFBQSxRQUNQO0FBQ0EsY0FBTSxvQkFBb0IsS0FBSyxLQUFLLHNCQUFzQixhQUFhLEVBQUU7QUFDekUsY0FBTSxrQkFBb0M7QUFBQSxVQUN4QyxFQUFFLHVCQUF1QixNQUFNLFVBQVU7QUFBQSxVQUN6QyxFQUFFLHVCQUF1QixNQUFNLFNBQVM7QUFBQSxVQUN4QyxFQUFFLHVCQUF1QixNQUFNLG1CQUFtQjtBQUFBLFVBQ2xELEVBQUUsdUJBQXVCLE1BQU0sZUFBZTtBQUFBLFVBQzlDLEVBQUUsdUJBQXVCLE1BQU0sd0JBQXdCO0FBQUEsVUFDdkQsRUFBRSx1QkFBdUIsTUFBTSxrQkFBa0I7QUFBQSxRQUNuRDtBQUNBLGNBQU0sV0FBVyw0QkFBNEIsTUFBTSxVQUFVLFVBQVU7QUFDdkUsY0FBTSxVQUFVLHlDQUEwQyxVQUFVO0FBQ3BFLGNBQU0sb0JBQXdELENBQUMsTUFBTTtBQUNyRSxZQUFJLFNBQVM7QUFDWCw0QkFBa0IsS0FBSyxNQUFNO0FBQUEsUUFDL0I7QUFDQSxZQUFJLDBCQUEwQjtBQUM1Qiw0QkFBa0IsS0FBSyxNQUFNO0FBQUEsUUFDL0I7QUFDQSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxnQkFBTSxjQUFjLGVBQWUsS0FBSyxNQUFNLFVBQVUsTUFBTSxNQUFNLFVBQVU7QUFDOUUsZ0JBQU0sZUFBZSxDQUFDLFdBQVc7QUFDakMsZ0JBQU0scUJBQXFCLFVBQVUsY0FBYyxZQUFZLFFBQVEsVUFBVSxRQUFRLElBQUksSUFBSTtBQUNqRyxjQUFJLG9CQUFvQjtBQUN0Qix5QkFBYSxLQUFLLGtCQUFrQjtBQUFBLFVBQ3RDO0FBRUEsZ0JBQU0saUNBQWlDLDJCQUNuQyxjQUFjLCtCQUErQix5QkFBeUIsVUFBVSx5QkFBeUIsSUFBSSxJQUM3RztBQUNKLGNBQUksZ0NBQWdDO0FBQ2xDLHlCQUFhLEtBQUssOEJBQThCO0FBQUEsVUFDbEQ7QUFDQSxnQkFBTSxnQkFBZ0IsMEJBQTBCLE1BQU0sUUFBUTtBQUM5RCxnQkFBTSxXQUE4QjtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxjQUFjLE1BQU0sTUFBTTtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxhQUFhLE1BQU0sTUFBTTtBQUFBLFlBQ2pDLEVBQUUsTUFBTSx3QkFBd0IsTUFBTSxNQUFNO0FBQUEsWUFDNUMsRUFBRSxNQUFNLG1CQUFtQixNQUFNLE1BQU07QUFBQSxZQUN2QyxFQUFFLE1BQU0seUJBQXlCLE1BQU0sTUFBTTtBQUFBLFlBQzdDLEVBQUUsTUFBTSx1QkFBdUIsTUFBTSxNQUFNO0FBQUEsVUFDN0M7QUFFQSxpQkFBTztBQUFBLDBDQUMrQixFQUFFO0FBQUEsMENBQ0YsRUFBRTtBQUFBLElBQ3hDLGFBQWEsaUJBQWlCLFFBQVEsRUFBRSxpQkFBaUIsR0FBRyxZQUFZLENBQUM7QUFBQSxJQUN6RSxhQUFhLFVBQVUsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE1BS2hDLFlBQVksb0JBQW9CLGdDQUFnQyxLQUFLLENBQUM7QUFBQTtBQUFBLGlDQUUzQyxFQUFFO0FBQUEsOEJBQ0wsVUFBVSxtREFBbUQsdUJBQXVCO0FBQUEsOEJBQ3BGLE9BQU87QUFBQTtBQUFBLGdDQUVMLE9BQU87QUFBQTtBQUFBLCtCQUVSLE1BQU07QUFDL0Isb0JBQVEsWUFBWTtBQUFBLGNBQ2xCLEtBQUs7QUFDSCx1QkFBTztBQUFBLGNBQ1QsS0FBSztBQUNILHVCQUFPO0FBQUEsY0FDVCxLQUFLO0FBQ0gsdUJBQU87QUFBQSxjQUNUO0FBQ0Usc0JBQU0sSUFBSSxNQUFNLDJCQUEyQixVQUFVLEVBQUU7QUFBQSxZQUMzRDtBQUFBLFVBQ0YsR0FBRyxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUEsMkJBSW1CLEVBQUU7QUFBQTtBQUFBO0FBQUE7QUFBQSx1QkFJTixPQUFPO0FBQUE7QUFBQSwwQkFFSixPQUFPO0FBQUE7QUFBQSwrQkFFRixNQUFNO0FBQy9CLG9CQUFRLFlBQVk7QUFBQSxjQUNsQixLQUFLO0FBQ0gsdUJBQU87QUFBQSxjQUNULEtBQUs7QUFDSCx1QkFBTztBQUFBLGNBQ1QsS0FBSztBQUNILHVCQUFPO0FBQUEsY0FDVDtBQUNFLHNCQUFNLElBQUksTUFBTSwyQkFBMkIsVUFBVSxFQUFFO0FBQUEsWUFDM0Q7QUFBQSxVQUNGLEdBQUcsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBLDJCQUltQixFQUFFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLDBCQU1ILFlBQVksS0FBSyxLQUFLLElBQUksYUFBYSxXQUFXLGFBQWE7QUFBQTtBQUFBO0FBQUE7QUFBQSx5QkFJaEUsT0FBTztBQUFBLDBCQUNOLFlBQVksS0FBSyxLQUFLO0FBQUE7QUFBQTtBQUFBLFFBSXhDLFVBQ0k7QUFBQTtBQUFBLHVDQUUyQixZQUFZLEtBQUssS0FBSyxJQUFJLGFBQWE7QUFBQSxhQUVsRSxFQUNOO0FBQUE7QUFBQSxRQUVKO0FBRUEsZUFBTztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sYUFBYSxFQUFFLE1BQU0sR0FBRyxFQUFFLElBQUksUUFBUSxJQUFJLFVBQVUsSUFBSSxrQkFBa0I7QUFBQSxVQUMxRTtBQUFBLFVBQ0EsWUFBWSxPQUFPO0FBQUEsWUFDakIsU0FBUyxDQUFDO0FBQUEsWUFDVixlQUFlLEVBQUUsR0FBRyxHQUFHLEdBQUcsZ0JBQWdCLEdBQUcsWUFBWSxTQUFTO0FBQUEsWUFDbEU7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFQSxNQUFNLGtDQUFrQyxDQUN0QyxhQUNBLEdBQ0EsS0FDQSxTQUNBLGVBQ0EsWUFDQSxvQkFDQSxTQUNBLDZCQUNHO0FBQ0gsY0FBTSxzQkFBc0IscUJBQXFCLFdBQVc7QUFDNUQsY0FBTSxhQUFhLENBQUMsV0FBVyxXQUFXLFdBQVcsVUFBVSxXQUFXLGdCQUFnQixtQkFBbUI7QUFDN0csY0FBTSxhQUFhLGNBQWMsS0FBSztBQUN0QyxjQUFNLGFBQWEsV0FBVyxhQUFhLFdBQVcsYUFBYSxXQUFXO0FBQzlFLGNBQU0sa0JBQWtCLGFBQ3BCLENBQUMsV0FBVyxXQUFXLFlBQVkscUJBQXFCLFdBQVcsUUFBUSxJQUMzRTtBQUNKLGNBQU0sUUFBUSxXQUFXLFFBQVEsV0FBVyxRQUFRO0FBR3BELGNBQU0sUUFBUSxXQUFXLFVBQVUsSUFBSSxJQUFNLEtBQUssS0FBSyxXQUFXLFFBQVEsSUFBSSxXQUFXO0FBQ3pGLGNBQU0sYUFBYSxpQkFBaUIsV0FBVyxRQUFRO0FBQ3ZELGNBQU0scUJBQXFCLFdBQVcsV0FBVztBQUNqRCxjQUFNLFlBQVk7QUFDbEIsY0FBTSxXQUFXO0FBQUEsVUFDZixHQUFHLEtBQUssS0FBSyxzQkFBc0IsU0FBUztBQUFBLFVBQzVDLEdBQUcsS0FBSyxLQUFLLFdBQVcsaUJBQWlCLFNBQVM7QUFBQSxVQUNsRCxHQUFHLFdBQVcsWUFBWSxXQUFXO0FBQUEsUUFDdkM7QUFDQSxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVyxlQUFlO0FBQUEsVUFDekQsRUFBRSx1QkFBdUIsTUFBTSxtQkFBbUI7QUFBQSxVQUNsRCxFQUFFLHVCQUF1QixNQUFNLG9CQUFvQjtBQUFBLFVBQ25ELEVBQUUsdUJBQXVCLE1BQU0sV0FBVyxTQUFTO0FBQUEsVUFDbkQsRUFBRSx1QkFBdUIsTUFBTSxXQUFXLFNBQVM7QUFBQSxVQUNuRCxFQUFFLHFCQUFzQixNQUFNLE1BQU07QUFBQSxVQUNwQyxFQUFFLHVCQUF1QixNQUFNLG1CQUFtQjtBQUFBLFVBQ2xELEVBQUUsdUJBQXVCLE1BQU0sV0FBVyxpQkFBaUI7QUFBQSxVQUMzRCxFQUFFLHVCQUF1QixNQUFNLE1BQU07QUFBQSxRQUN2QztBQUVBLGNBQU0sY0FBYyxjQUFjLFdBQVcsVUFBVSxLQUFLLFFBQVEsSUFBSSxJQUFJO0FBQzVFLGNBQU0sb0JBQXdELENBQUMsUUFBUSxNQUFNO0FBQzdFLFlBQUksYUFBYTtBQUNmLDRCQUFrQixLQUFLLE1BQU07QUFBQSxRQUMvQjtBQUNBLFlBQUksZUFBZTtBQUNqQiw0QkFBa0IsS0FBSyxNQUFNO0FBQUEsUUFDL0I7QUFDQSxZQUFJLFNBQVM7QUFDWCw0QkFBa0IsS0FBSyxNQUFNO0FBQUEsUUFDL0I7QUFDQSxZQUFJLDBCQUEwQjtBQUM1Qiw0QkFBa0IsS0FBSyxNQUFNO0FBQUEsUUFDL0I7QUFDQSxjQUFNLFVBQVUsQ0FBQyxFQUFFLE1BQU0sWUFBWSxVQUFVLEVBQUUsVUFBVSw2QkFBaUMsQ0FBQztBQUM3RixZQUFJLFlBQVk7QUFDZCxrQkFBUSxLQUFLLEVBQUUsTUFBTSxpQkFBa0IsVUFBVSxFQUFFLFVBQVUsNkJBQWlDLENBQUM7QUFBQSxRQUNqRztBQUNBLGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQ3RELGdCQUFNLFNBQVMsY0FBYyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sVUFBVTtBQUNoRSxnQkFBTSxTQUFTLGNBQWMsT0FBTyxJQUFJLFVBQVUsSUFBSSxNQUFNLFVBQVU7QUFDdEUsZ0JBQU0sWUFBWSxDQUFDLFFBQVEsTUFBTTtBQUNqQyxjQUFJLGFBQWE7QUFDZixrQkFBTSxlQUFlLGNBQWMsWUFBWSxRQUFRLFVBQVUsUUFBUSxNQUFNLFVBQVU7QUFDekYsc0JBQVUsS0FBSyxZQUFZO0FBQUEsVUFDN0I7QUFDQSxjQUFJLGVBQWU7QUFDakIsc0JBQVUsS0FBSyxjQUFjLGtCQUFrQixjQUFjLFVBQVUsY0FBYyxJQUFJLENBQUM7QUFBQSxVQUM1RjtBQUNBLGdCQUFNLHVCQUF1QixVQUFVLGNBQWMsWUFBWSxRQUFRLFVBQVUsUUFBUSxJQUFJLElBQUk7QUFDbkcsY0FBSSxzQkFBc0I7QUFDeEIsc0JBQVUsS0FBSyxvQkFBb0I7QUFBQSxVQUNyQztBQUNBLGdCQUFNLG1DQUFtQywyQkFDckMsY0FBYywrQkFBK0IseUJBQXlCLFVBQVUseUJBQXlCLElBQUksSUFDN0c7QUFDSixjQUFJLGtDQUFrQztBQUNwQyxzQkFBVSxLQUFLLGdDQUFnQztBQUFBLFVBQ2pEO0FBQ0EsZ0JBQU0sU0FBUyxlQUFlLFVBQVUsRUFBRSxVQUFVLFVBQVU7QUFDOUQsZ0JBQU0sYUFBYSxDQUFDLE1BQU07QUFDMUIsY0FBSSxZQUFZO0FBQ2QsdUJBQVcsS0FBSyxlQUFlLGVBQWUsRUFBRSxVQUFVLGlCQUFrQixVQUFVLENBQUM7QUFBQSxVQUN6RjtBQUNBLGdCQUFNLFVBQVUseUNBQTBDLFVBQVU7QUFFcEUsZ0JBQU0sV0FBOEI7QUFBQSxZQUNsQyxFQUFFLE1BQU0sS0FBSyxNQUFNLE1BQU07QUFBQSxZQUN6QixFQUFFLE1BQU0sS0FBSyxNQUFNLE1BQU07QUFBQSxZQUN6QixFQUFFLE1BQU0sS0FBSyxNQUFNLE1BQU07QUFBQSxZQUN6QixFQUFFLE1BQU0sYUFBYSxNQUFNLE1BQU07QUFBQSxZQUNqQyxFQUFFLE1BQU0sYUFBYSxNQUFNLE1BQU07QUFBQSxZQUNqQyxFQUFFLE1BQU0sU0FBUyxNQUFNLE1BQWdDO0FBQUEsWUFDdkQsRUFBRSxNQUFNLHdCQUF3QixNQUFNLE1BQU07QUFBQSxZQUM1QyxFQUFFLE1BQU0sc0JBQXNCLE1BQU0sTUFBTTtBQUFBLFlBQzFDLEVBQUUsTUFBTSxVQUFVLE1BQU0sTUFBTTtBQUFBLFVBQ2hDO0FBQ0EsaUJBQU87QUFBQSxzQkFDVyxTQUFTO0FBQUE7QUFBQSxnQ0FFQyxPQUFPLEtBQUssT0FBTyxLQUFLLFlBQVksU0FBUztBQUFBLGdDQUM3QyxPQUFPLEtBQUssT0FBTyxLQUFLLFlBQVksU0FBUztBQUFBLElBQ3pFLGFBQWEsaUJBQWlCLFFBQVEsRUFBRSxpQkFBaUIsR0FBRyxXQUFXLEdBQUcsVUFBVSxDQUFDO0FBQUEsSUFDckYsYUFBYSxVQUFVLENBQUMsV0FBVyxXQUFXLENBQUMsQ0FBQyxDQUFDO0FBQUE7QUFBQTtBQUFBLHNCQUcvQixVQUFVLElBQUksWUFBWSwyQkFBMkI7QUFBQSx5QkFDbEQsVUFBVSxJQUFJLHVCQUF1QixzQ0FBc0M7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsTUFNOUYsWUFBWSxzQkFBc0Isa0NBQWtDLElBQUksQ0FBQztBQUFBO0FBQUE7QUFBQSxNQUd6RSxlQUFlLGFBQWEsbUZBQW1GLEVBQUU7QUFBQTtBQUFBLE1BRWpILGFBQWEsbUVBQW1FLEVBQUU7QUFBQSxrQkFDdEUsT0FBTztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFNBT2hCLE1BQU07QUFDUCxnQkFBSSxlQUFlLFlBQVk7QUFDN0IscUJBQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsWUFNVCxPQUFPO0FBQ0wscUJBQU87QUFBQTtBQUFBO0FBQUE7QUFBQSxZQUlUO0FBQUEsVUFDRixHQUFHLENBQUM7QUFBQSxRQUVGLGFBQ0k7QUFBQTtBQUFBLFdBR0EsRUFDTjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEscUJBS2UsT0FBTztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSx3QkFTSixNQUFNO0FBQ3RCLG9CQUFRLFlBQVk7QUFBQSxjQUNsQixLQUFLO0FBQ0gsdUJBQU87QUFBQSxjQUNULEtBQUs7QUFDSCx1QkFBTztBQUFBLGNBQ1QsS0FBSztBQUNILHVCQUFPO0FBQUEsY0FDVDtBQUNFLHNCQUFNLElBQUksTUFBTSwyQkFBMkIsVUFBVSxFQUFFO0FBQUEsWUFDM0Q7QUFBQSxVQUNGLEdBQUcsQ0FBQztBQUFBLDhCQUNvQixPQUFPLEtBQUssS0FBSyw2QkFDckMsZ0JBQWdCLDhCQUE4QixLQUNoRDtBQUFBO0FBQUE7QUFBQSxRQUdOO0FBQ0EsZUFBTztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sYUFBYTtBQUFBLFlBQ1gsTUFBTSxHQUFHLFVBQVUsSUFBSSxrQkFBa0IsTUFBUyxJQUFJLFlBQVksTUFBUyxJQUFJLFdBQVc7QUFBQSxZQUMxRjtBQUFBLFVBQ0Y7QUFBQSxVQUNBLFlBQVksT0FBTyxFQUFFLFNBQVMsZUFBZSxVQUFVLGdCQUFnQjtBQUFBLFVBQ3ZFO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFQSxNQUFNLG9DQUFvQyxDQUN4QyxhQUNBLE9BQ0EsR0FDQSxXQUNBLFFBQ0Esb0JBQ0EsVUFBa0MsUUFDbEMsMkJBQW1ELFdBQ2hEO0FBQ0gsY0FBTSxzQkFBc0IscUJBQXFCLE9BQU87QUFDeEQsY0FBTSxRQUFRLE9BQU8sUUFBUSxPQUFPLFFBQVE7QUFDNUMsY0FBTSxzQkFBc0IsT0FBTyxjQUFjO0FBQ2pELGNBQU0sZUFBZSxjQUFjLEtBQUs7QUFDeEMsY0FBTSxhQUFhLE9BQU8sYUFBYSxPQUFPLGFBQWEsT0FBTztBQUNsRSxjQUFNLG9CQUFvQixlQUN0QixDQUFDLE9BQU8sV0FBVyxZQUFZLHFCQUFxQixPQUFPLFFBQVEsSUFDbkU7QUFDSixjQUFNLGNBQWMsQ0FBQyxPQUFPLFdBQVcsT0FBTyxnQkFBZ0IsbUJBQW1CO0FBQ2pGLGNBQU0sWUFBWTtBQUNsQixjQUFNLFdBQVc7QUFBQSxVQUNmLEdBQUcsS0FBSyxLQUFLLE9BQU8sWUFBWSxTQUFTO0FBQUEsVUFDekMsR0FBRyxLQUFLLEtBQUssT0FBTyxpQkFBaUIsU0FBUztBQUFBLFVBQzlDLEdBQUcsT0FBTyxZQUFZLE9BQU87QUFBQSxRQUMvQjtBQUVBLGNBQU0sa0JBQW9DO0FBQUEsVUFDeEMsRUFBRSx1QkFBdUIsTUFBTSxPQUFPLGVBQWU7QUFBQSxVQUNyRCxFQUFFLHVCQUF1QixNQUFNLG9CQUFvQjtBQUFBLFVBQ25ELEVBQUUsdUJBQXVCLE1BQU0sT0FBTyxVQUFVO0FBQUEsVUFDaEQsRUFBRSx1QkFBdUIsTUFBTSxPQUFPLFNBQVM7QUFBQSxVQUMvQyxFQUFFLHVCQUF1QixNQUFNLE9BQU8sU0FBUztBQUFBLFVBQy9DLEVBQUUsdUJBQXVCLE1BQU0sb0JBQW9CO0FBQUEsVUFDbkQsRUFBRSx1QkFBdUIsTUFBTSxtQkFBbUI7QUFBQSxVQUNsRCxFQUFFLHVCQUF1QixNQUFNLE9BQU8saUJBQWlCO0FBQUEsVUFDdkQsRUFBRSx1QkFBdUIsTUFBTSxNQUFNO0FBQUEsUUFDdkM7QUFFQSxjQUFNLGdCQUFnQixnQkFBZ0IsYUFBYSxVQUFVLEtBQUssVUFBVSxJQUFJLElBQUk7QUFDcEYsY0FBTSxvQkFBd0QsQ0FBQyxRQUFRLE1BQU07QUFDN0UsWUFBSSxlQUFlO0FBQ2pCLDRCQUFrQixLQUFLLE1BQU07QUFBQSxRQUMvQjtBQUNBLFlBQUksU0FBUztBQUNYLDRCQUFrQixLQUFLLE1BQU07QUFBQSxRQUMvQjtBQUNBLFlBQUksMEJBQTBCO0FBQzVCLDRCQUFrQixLQUFLLE1BQU07QUFBQSxRQUMvQjtBQUNBLGNBQU0sVUFBVSxDQUFDLEVBQUUsTUFBTSxhQUFhLFVBQVUsTUFBTSxVQUFVLDZCQUFpQyxDQUFDO0FBQ2xHLFlBQUksY0FBYztBQUNoQixrQkFBUSxLQUFLLEVBQUUsTUFBTSxtQkFBb0IsVUFBVSxNQUFNLFVBQVUsNkJBQWlDLENBQUM7QUFBQSxRQUN2RztBQUNBLGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQ3RELGdCQUFNLGNBQWMsY0FBYyxTQUFTLE1BQU0sVUFBVSxNQUFNLElBQUk7QUFDckUsZ0JBQU0sVUFBVSxjQUFjLEtBQUssRUFBRSxVQUFVLEVBQUUsSUFBSTtBQUNyRCxnQkFBTSxZQUFZLENBQUMsYUFBYSxPQUFPO0FBQ3ZDLGNBQUksZUFBZTtBQUNqQixzQkFBVSxLQUFLLGNBQWMsY0FBYyxVQUFVLFVBQVUsVUFBVSxJQUFJLENBQUM7QUFBQSxVQUNoRjtBQUNBLGdCQUFNLHVCQUF1QixVQUFVLGNBQWMsWUFBWSxRQUFRLFVBQVUsUUFBUSxJQUFJLElBQUk7QUFDbkcsY0FBSSxTQUFTO0FBQ1gsc0JBQVUsS0FBSyxvQkFBcUI7QUFBQSxVQUN0QztBQUNBLGdCQUFNLG1DQUFtQywyQkFDckMsY0FBYywrQkFBK0IseUJBQXlCLFVBQVUseUJBQXlCLElBQUksSUFDN0c7QUFDSixjQUFJLDBCQUEwQjtBQUM1QixzQkFBVSxLQUFLLGdDQUFpQztBQUFBLFVBQ2xEO0FBQ0EsZ0JBQU0sU0FBUyxlQUFlLFVBQVUsTUFBTSxVQUFVLFdBQVc7QUFDbkUsZ0JBQU0sYUFBYSxDQUFDLE1BQU07QUFDMUIsY0FBSSxjQUFjO0FBQ2hCLHVCQUFXLEtBQUssZUFBZSxpQkFBaUIsTUFBTSxVQUFVLGlCQUFrQixDQUFDO0FBQUEsVUFDckY7QUFDQSxnQkFBTSxXQUE4QjtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxLQUFLLE1BQU0sTUFBTTtBQUFBLFlBQ3pCLEVBQUUsTUFBTSxLQUFLLE1BQU0sTUFBTTtBQUFBLFlBQ3pCLEVBQUUsTUFBTSxLQUFLLE1BQU0sTUFBTTtBQUFBLFlBQ3pCLEVBQUUsTUFBTSxhQUFhLE1BQU0sTUFBTTtBQUFBLFlBQ2pDLEVBQUUsTUFBTSxhQUFhLE1BQU0sTUFBTTtBQUFBLFlBQ2pDLEVBQUUsTUFBTSxpQkFBaUIsTUFBTSxNQUFNO0FBQUEsWUFDckMsRUFBRSxNQUFNLHdCQUF3QixNQUFNLE1BQU07QUFBQSxZQUM1QyxFQUFFLE1BQU0sc0JBQXNCLE1BQU0sTUFBTTtBQUFBLFlBQzFDLEVBQUUsTUFBTSxVQUFVLE1BQU0sTUFBTTtBQUFBLFVBQ2hDO0FBQ0EsaUJBQU87QUFBQSxzQkFDVyxTQUFTO0FBQUEsZ0NBQ0MsWUFBWSxLQUFLLEtBQUssS0FBSyxZQUFZLFNBQVM7QUFBQSxnQ0FDaEQsWUFBWSxLQUFLLEtBQUssS0FBSyxZQUFZLFNBQVM7QUFBQSxJQUM1RSxhQUFhLGlCQUFpQixRQUFRLEVBQUUsaUJBQWlCLEdBQUcsV0FBVyxHQUFHLFVBQVUsQ0FBQztBQUFBLElBQ3JGLGFBQWEsVUFBVSxDQUFDLFdBQVcsV0FBVyxDQUFDLENBQUMsQ0FBQztBQUFBO0FBQUE7QUFBQSxxQkFHaEMsVUFBVSxJQUFJLFlBQVksMkJBQTJCO0FBQUEsd0JBQ2xELFVBQVUsSUFBSSx1QkFBdUIsc0NBQXNDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxLQUs5RixZQUFZLHNCQUFzQixrQ0FBa0MsSUFBSSxDQUFDO0FBQUE7QUFBQTtBQUFBLEtBR3pFLGlCQUFpQixlQUFlLHlGQUF5RixFQUFFO0FBQUE7QUFBQSxLQUUzSCxlQUFlLHlFQUF5RSxFQUFFO0FBQUEsaUJBQzlFLFlBQVksS0FBSyxPQUFPO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsV0FPOUIsTUFBTTtBQUNQLGdCQUFJLGlCQUFpQixjQUFjO0FBQ2pDLHFCQUFPO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsWUFPVCxPQUFPO0FBQ0wscUJBQU87QUFBQTtBQUFBO0FBQUE7QUFBQSxZQUlUO0FBQUEsVUFDRixHQUFHLENBQUM7QUFBQSxVQUVGLGVBQ0k7QUFBQTtBQUFBO0FBQUEsYUFJQSxFQUNOO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFnQk47QUFFQSxlQUFPO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixhQUFhLEVBQUUsTUFBTSxHQUFHLGNBQWMsTUFBUyxJQUFJLFdBQVcsSUFBSSxrQkFBa0I7QUFBQSxVQUNwRixZQUFZLE9BQU8sRUFBRSxTQUFTLGVBQWUsVUFBVSxnQkFBZ0I7QUFBQSxVQUN2RTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxpQkFBaUIsQ0FDNUIsU0FDQSxHQUNBLEdBQ0EsR0FDQSxZQUNBLE9BQ0EsU0FDQSxXQUNBLG9CQUNBLFlBQ0EsVUFBa0MsUUFDbEMsMkJBQW1ELFdBQ2hEO0FBRUgsY0FBTSxjQUFjLEtBQUssSUFBSSxRQUFRLGFBQWEsS0FBSyxVQUFVLElBQUksTUFBTSxZQUFZLElBQUksRUFBRTtBQUM3RixjQUFNLHFCQUFxQixjQUFjLElBQUksV0FBVyxxQkFBcUI7QUFDN0UsY0FBTSxzQkFBc0IscUJBQXFCLFdBQVc7QUFDNUQsY0FBTSxnQkFDSixzQkFBc0IsVUFBVSxLQUFLLG1CQUFtQixJQUFJLElBQUksSUFBSSxxQkFBcUI7QUFFM0YsY0FBTSxVQUFVLENBQUMsR0FBRyxDQUFDO0FBQ3JCLFlBQUksY0FBYyxLQUFLLFdBQVcsVUFBVSxLQUFLLFFBQVEsSUFBSSxJQUFJLEdBQUc7QUFDbEUsa0JBQVEsS0FBSyxPQUFPO0FBQUEsUUFDdEI7QUFDQSxZQUFJLGVBQWU7QUFDakIsa0JBQVEsS0FBSyxhQUFhO0FBQUEsUUFDNUI7QUFDQSxZQUFJLFNBQVM7QUFDWCxrQkFBUSxLQUFLLE9BQU87QUFBQSxRQUN0QjtBQUNBLFlBQUksMEJBQTBCO0FBQzVCLGtCQUFRLEtBQUssd0JBQXdCO0FBQUEsUUFDdkM7QUFFQSxjQUFNLFFBQVEsUUFBUTtBQUFBLFVBQ3BCO0FBQUEsWUFDRTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUFBLFVBQ0EsRUFBRSxRQUFRLFNBQVMsU0FBUyxjQUFjLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRTtBQUFBLFFBQy9ELEVBQUUsQ0FBQztBQUdILGdCQUFRO0FBQUEsVUFDTjtBQUFBLFlBQ0U7QUFBQSxZQUNBLFdBQVc7QUFBQSxZQUNYLFdBQVc7QUFBQSxZQUNYO0FBQUEsWUFDQSxXQUFXO0FBQUEsWUFDWDtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUFBLFVBQ0EsRUFBRSxRQUFRLFdBQVcsMkJBQTJCLENBQUMsT0FBTyxTQUFTLHdCQUF3QixJQUFJLENBQUMsS0FBSyxHQUFHLFNBQVMsQ0FBQyxFQUFFO0FBQUEsUUFDcEg7QUFHQSxjQUFNLFVBQVUsQ0FBQyxPQUFPLENBQUM7QUFDekIsWUFBSSxjQUFjLEtBQUssYUFBYSxVQUFVLEtBQUssVUFBVSxJQUFJLElBQUksR0FBRztBQUN0RSxrQkFBUSxLQUFLLFNBQVM7QUFBQSxRQUN4QjtBQUNBLFlBQUksU0FBUztBQUNYLGtCQUFRLEtBQUssT0FBTztBQUFBLFFBQ3RCO0FBQ0EsWUFBSSwwQkFBMEI7QUFDNUIsa0JBQVEsS0FBSyx3QkFBd0I7QUFBQSxRQUN2QztBQUNBLGdCQUFRO0FBQUEsVUFDTjtBQUFBLFlBQ0U7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUFBLFVBQ0E7QUFBQSxZQUNFLFFBQVE7QUFBQSxZQUNSLFNBQVMsY0FBYyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQUEsVUFDeEM7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVBLE1BQU0sVUFBVSxDQUFDLFNBQXlCLGVBQW9DO0FBQzVFLGNBQU0sY0FBYyxDQUFDLFdBQVcsV0FBVyxXQUFXLFVBQVUsV0FBVyxnQkFBZ0IsV0FBVyxRQUFRO0FBQzlHLGNBQU0sSUFBSSxXQUFXO0FBQ3JCLGNBQU0sSUFBSSxXQUFXO0FBQ3JCLGNBQU0sSUFBSSxXQUFXO0FBQ3JCLGNBQU0sWUFBWTtBQUNsQixjQUFNLFdBQVc7QUFBQSxVQUNmLEdBQUcsS0FBSyxLQUFLLFdBQVcsV0FBVyxTQUFTO0FBQUEsVUFDNUMsR0FBRyxLQUFLLEtBQUssV0FBVyxpQkFBaUIsU0FBUztBQUFBLFVBQ2xELEdBQUcsV0FBVyxZQUFZLFdBQVc7QUFBQSxRQUN2QztBQUNBLGNBQU0sU0FBUyxDQUFDLFFBQVEsT0FBTyxDQUFDLEdBQUcsUUFBUSxPQUFPLENBQUMsR0FBRyxRQUFRLE9BQU8sQ0FBQyxDQUFDO0FBQ3ZFLGNBQU0sa0JBQW9DO0FBQUEsVUFDeEMsRUFBRSx1QkFBdUIsTUFBTSxFQUFFO0FBQUEsVUFDakMsRUFBRSx1QkFBdUIsTUFBTSxFQUFFO0FBQUEsVUFDakMsRUFBRSx1QkFBdUIsTUFBTSxFQUFFO0FBQUEsVUFDakMsRUFBRSx1QkFBdUIsTUFBTSxXQUFXLFNBQVM7QUFBQSxVQUNuRCxFQUFFLHVCQUF1QixNQUFNLFdBQVcsU0FBUztBQUFBLFVBQ25ELEVBQUUsdUJBQXVCLE1BQU0sV0FBVyxXQUFXO0FBQUEsVUFDckQsRUFBRSx1QkFBdUIsTUFBTSxXQUFXLGFBQWEsV0FBVyxhQUFhLFdBQVcsWUFBWTtBQUFBLFFBQ3hHO0FBRUEsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFDdEQsZ0JBQU0sVUFBVSxlQUFlLFlBQVksT0FBTyxDQUFDLEVBQUUsVUFBVSxXQUFXO0FBQzFFLGdCQUFNLFVBQVUsZUFBZSxZQUFZLE9BQU8sQ0FBQyxFQUFFLFVBQVUsV0FBVztBQUMxRSxnQkFBTSxVQUFVLGVBQWUsWUFBWSxPQUFPLENBQUMsRUFBRSxVQUFVLFdBQVc7QUFDMUUsZ0JBQU0sUUFBUSxjQUFjLFNBQVMsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxJQUFJO0FBQ3ZFLGdCQUFNLFNBQVMsY0FBYyxVQUFVLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxDQUFDLEVBQUUsSUFBSTtBQUN6RSxnQkFBTSxPQUFPLGNBQWMsUUFBUSxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLElBQUk7QUFDckUsZ0JBQU0sV0FBVyxNQUFNLEtBQUs7QUFFNUIsZ0JBQU0sV0FBOEI7QUFBQSxZQUNsQyxFQUFFLE1BQU0sS0FBSyxNQUFNLE1BQU07QUFBQSxZQUN6QixFQUFFLE1BQU0sS0FBSyxNQUFNLE1BQU07QUFBQSxZQUN6QixFQUFFLE1BQU0sS0FBSyxNQUFNLE1BQU07QUFBQSxZQUN6QixFQUFFLE1BQU0sYUFBYSxNQUFNLE1BQU07QUFBQSxZQUNqQyxFQUFFLE1BQU0sYUFBYSxNQUFNLE1BQU07QUFBQSxZQUNqQyxFQUFFLE1BQU0sZUFBZSxNQUFNLE1BQU07QUFBQSxZQUNuQyxFQUFFLE1BQU0sT0FBTyxNQUFNLE1BQU07QUFBQSxVQUM3QjtBQUNBLGlCQUFPO0FBQUEsc0JBQ1csU0FBUztBQUFBLG9DQUNLLFFBQVEsS0FBSyxZQUFZLFNBQVM7QUFBQSxzQ0FDaEMsUUFBUSxLQUFLLFlBQVksU0FBUztBQUFBLHNDQUNsQyxRQUFRLEtBQUssWUFBWSxTQUFTO0FBQUEsc0NBQ2xDLFFBQVEsS0FBSyxZQUFZLFNBQVM7QUFBQSxJQUNwRSxhQUFhLGlCQUFpQixRQUFRLEVBQUUsaUJBQWlCLE9BQU8sUUFBUSxNQUFNLFNBQVMsU0FBUyxPQUFPLENBQUM7QUFBQSxJQUN4RyxhQUFhLFVBQVUsQ0FBQyxXQUFXLFdBQVcsQ0FBQyxDQUFDLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLG1CQVdsQyxRQUFRO0FBQUEsbUJBQ1IsUUFBUTtBQUFBLG1CQUNSLFFBQVE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFvQ3pCO0FBRUEsZUFBTyxRQUFRO0FBQUEsVUFDYjtBQUFBLFlBQ0UsTUFBTTtBQUFBLFlBQ04sYUFBYSxFQUFFLG1CQUFtQixDQUFDLFFBQVEsUUFBUSxNQUFNLEVBQUU7QUFBQSxZQUMzRCxZQUFZLE9BQU87QUFBQSxjQUNqQixTQUFTO0FBQUEsZ0JBQ1AsRUFBRSxNQUFNLGFBQWEsVUFBVSxRQUFRLE9BQU8sQ0FBQyxFQUFFLFVBQVUsNkJBQWlDO0FBQUEsZ0JBQzVGLEVBQUUsTUFBTSxhQUFhLFVBQVUsUUFBUSxPQUFPLENBQUMsRUFBRSxVQUFVLDZCQUFpQztBQUFBLGdCQUM1RixFQUFFLE1BQU0sYUFBYSxVQUFVLFFBQVEsT0FBTyxDQUFDLEVBQUUsVUFBVSw2QkFBaUM7QUFBQSxjQUM5RjtBQUFBLGNBQ0EsZUFBZTtBQUFBLGNBQ2Y7QUFBQSxZQUNGO0FBQUEsWUFDQTtBQUFBLFVBQ0Y7QUFBQSxVQUNBLEVBQUUsUUFBUSxTQUFTLENBQUMsSUFBSSxJQUFJLEVBQUUsRUFBRTtBQUFBLFFBQ2xDO0FBQUEsTUFDRjtBQUVPLE1BQU0sWUFBWSxDQUFDLFNBQXlCLGVBQXFDO0FBQ3RGLGNBQU0sU0FBUyx3QkFBd0IsUUFBUSxRQUFRLFVBQVU7QUFFakUsY0FBTSxDQUFDLEdBQUcsR0FBRyxDQUFDLElBQUksUUFBUSxTQUFTLE1BQU07QUFFekMsZUFBTztBQUFBLFVBQ0w7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBLFFBQVEsT0FBTyxDQUFDO0FBQUEsVUFDaEI7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0EsUUFBUSxPQUFPLENBQUM7QUFBQSxVQUNoQjtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBQUE7QUFBQTs7O0FDLy9CQSxNQXNCTUMsaUJBb0NBLHFDQWdGTywwQkFHQTtBQTdJYjtBQUFBO0FBQUE7QUFHQTtBQUVBO0FBRUE7QUFDQTtBQUdBO0FBV0EsTUFBTUEsa0JBQWlCLENBQUMsUUFBK0IsZUFBMEM7QUFDL0YsWUFBSSxDQUFDLFVBQVUsT0FBTyxXQUFXLEdBQUc7QUFDbEMsZ0JBQU0sSUFBSSxNQUFNLHNDQUFzQztBQUFBLFFBQ3hEO0FBRUEsY0FBTSxrQkFBa0IsQ0FBQyxRQUEyQixVQUE2QixZQUFvQjtBQUNuRyxnQkFBTSxJQUFJLFNBQVM7QUFDbkIsY0FBSSxNQUFNLE9BQU8sUUFBUTtBQUN2QixrQkFBTSxJQUFJLE1BQU0sR0FBRyxPQUFPLHVCQUF1QixDQUFDLEVBQUU7QUFBQSxVQUN0RDtBQUNBLG1CQUFTLFFBQVEsQ0FBQyxHQUFHLE1BQU07QUFDekIsZ0JBQUksTUFBTSxPQUFPLENBQUMsR0FBRztBQUNuQixvQkFBTSxJQUFJLE1BQU0sR0FBRyxPQUFPLFNBQVMsQ0FBQyxnQkFBZ0I7QUFBQSxZQUN0RDtBQUFBLFVBQ0YsQ0FBQztBQUFBLFFBQ0g7QUFFQSxZQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssU0FBUyxHQUFHO0FBQzdCLGdCQUFNLFFBQ0osV0FBVyxXQUFXLFNBQ2xCLFdBQVcsVUFDVCxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU0sRUFBRSxJQUN2QixPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU0sRUFBRSxFQUFFLE9BQU8sT0FBTyxDQUFDLEVBQUUsS0FBSyxNQUFNLEdBQUcsT0FBTyxDQUFDLEVBQUUsS0FBSyxTQUFTLENBQUMsQ0FBQyxJQUNwRixPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU0sR0FBRyxXQUFXLFVBQVUsSUFBSSxNQUFTO0FBQ2hFLDBCQUFnQixPQUFPLENBQUMsRUFBRSxNQUFNLE9BQU8scUJBQXFCO0FBQzVELDBCQUFnQixPQUFPLENBQUMsRUFBRSxNQUFNLE9BQU8saUJBQWlCO0FBQ3hELDBCQUFnQixPQUFPLENBQUMsRUFBRSxNQUFNLE9BQU8sb0JBQW9CO0FBQzNELDBCQUFnQixPQUFPLENBQUMsRUFBRSxNQUFNLE9BQU8sbUJBQW1CO0FBQUEsUUFDNUQsT0FBTztBQUNMLDBCQUFnQixPQUFPLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxHQUFHLHFCQUFxQjtBQUMxRCwwQkFBZ0IsT0FBTyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUMsR0FBRyxpQkFBaUI7QUFDdEQsMEJBQWdCLE9BQU8sQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLEdBQUcsb0JBQW9CO0FBQ3pELDBCQUFnQixPQUFPLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxHQUFHLG1CQUFtQjtBQUFBLFFBQzFEO0FBQUEsTUFDRjtBQUVBLE1BQU0sc0NBQXNDLENBQzFDLFFBQ0EsZUFDZ0I7QUFDaEIsY0FBTSxFQUFFLFNBQVMsU0FBUyxPQUFPLElBQUk7QUFDckMsY0FBTSxTQUFTLE9BQU8sQ0FBQyxFQUFFO0FBQ3pCLGNBQU0sYUFBYSxVQUFVLGlCQUFpQixPQUFPLE9BQU8sU0FBUyxDQUFDLENBQUMsSUFBSTtBQUMzRSxjQUFNLGNBQWMsV0FBVyxVQUFVLE9BQU8sU0FBUyxJQUFJLGFBQWE7QUFDMUUsY0FBTSxhQUFhLFVBQVUsS0FBSyxNQUFNLElBQUk7QUFFNUMsY0FBTSxvQkFBb0I7QUFDMUIsY0FBTSxjQUFjLG9CQUFvQixPQUFPLFNBQVM7QUFDeEQsY0FBTSxJQUFJLGNBQWMsS0FBSyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLE1BQU0sVUFBVTtBQUMzRSxjQUFNLFFBQVEsY0FBYyxTQUFTLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxDQUFDLEVBQUUsTUFBTSxXQUFXO0FBQ3BGLGNBQU0sT0FBTyxjQUFjLFFBQVEsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxNQUFNLFdBQVc7QUFDbEYsY0FBTSxZQUFZLGNBQWMsYUFBYSxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLE1BQU0sV0FBVztBQUM1RixjQUFNLFdBQVcsY0FBYyxZQUFZLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxDQUFDLEVBQUUsTUFBTSxXQUFXO0FBQzFGLGNBQU0sSUFBSSxlQUFlLEtBQUssT0FBTyxDQUFDLEVBQUUsVUFBVSxhQUFhLFVBQVU7QUFHekUsY0FBTSxjQUFjLE1BQWM7QUFDaEMsY0FBSSxVQUFVO0FBQ2QsY0FBSSxTQUFTO0FBQ1gsc0JBQVUsaUJBQ1IsT0FBTyxXQUFXLElBQ2QsT0FDQSxXQUFXLFNBQ1QsaUJBQWlCLE9BQU8sU0FBUyxDQUFDLE9BQU8sVUFBVSxLQUNuRCxrQkFDUjtBQUFBLFVBQ0YsT0FBTztBQUNMLGdCQUFJLFdBQVcsUUFBUTtBQUNyQix3QkFBVTtBQUFBLGNBQ0osRUFBRSxXQUFXLGlCQUFpQixLQUFLLEdBQUcsQ0FBQztBQUFBLDRCQUN6QixFQUFFLGdCQUFnQixlQUFlLENBQUM7QUFBQSxZQUN4RCxPQUFPO0FBRUwsd0JBQVUsa0JBQWtCLE1BQU0sS0FBSyxPQUFPO0FBQUEscURBQ0QsT0FBTyxTQUFTLENBQUM7QUFFOUQsdUJBQVMsSUFBSSxHQUFHLElBQUksTUFBTSxNQUFNLEtBQUs7QUFDbkMsMkJBQVcsWUFBWSxDQUFDLHFCQUFxQixDQUFDO0FBQUEsY0FDaEQ7QUFDQSx5QkFBVyxpQkFBaUIsTUFBTSxnQkFBZ0IsVUFBVSxDQUFDO0FBQUEsWUFDL0Q7QUFBQSxVQUNGO0FBQ0EsaUJBQU87QUFBQSxRQUNUO0FBQ0EsY0FBTSwrQkFBK0IsQ0FBQyxXQUF5QjtBQUFBLG9CQUM3QyxPQUFPO0FBQUEsSUFDdkIsT0FBTyxnQkFBZ0IsY0FBYyxLQUFLLEVBQUUsaUJBQWlCLEdBQUcsT0FBTyxNQUFNLFdBQVcsVUFBVSxDQUFDLENBQUM7QUFBQSxJQUNwRyxPQUFPLFVBQVUsQ0FBQztBQUFBLElBQ2xCLE9BQU8sc0NBQXNDLHFCQUFxQixDQUFDO0FBQUEsMEJBQzdDLEVBQUUsZ0JBQWdCLGdCQUFnQixVQUFVLEVBQUUsQ0FBQztBQUFBLE1BQ25FLFlBQVksQ0FBQztBQUFBLGtCQUNELE1BQU0sWUFBWSxTQUFTLENBQUM7QUFBQSxpQkFDN0IsS0FBSyxZQUFZLFNBQVMsQ0FBQztBQUFBLHNCQUN0QixVQUFVLFlBQVksU0FBUyxDQUFDO0FBQUEscUJBQ2pDLFNBQVMsWUFBWSxTQUFTLENBQUM7QUFBQSxjQUN0QyxFQUFFLFlBQVksWUFBWSxDQUFDO0FBQUE7QUFBQSxNQUVuQyxFQUFFLFlBQVksY0FBYyxPQUFPLENBQUM7QUFBQTtBQUV4QyxlQUFPO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixhQUFhO0FBQUEsWUFDWCxNQUFNLEdBQUcsV0FBVyxPQUFPLElBQUksV0FBVyxNQUFNLElBQUksT0FBTyxJQUFJLFVBQVU7QUFBQSxZQUN6RSxtQkFBbUIsb0JBQW9CLENBQUMsUUFBUSxRQUFRLFFBQVEsUUFBUSxNQUFNLElBQUk7QUFBQSxVQUNwRjtBQUFBLFVBQ0EsaUJBQWlCO0FBQUEsVUFDakIsWUFBWSxPQUFPO0FBQUEsWUFDakIsU0FBUyxDQUFDLEVBQUUsTUFBTSxPQUFPLENBQUMsRUFBRSxNQUFNLFVBQVUsT0FBTyxDQUFDLEVBQUUsU0FBUyxDQUFDO0FBQUEsWUFDaEUsZUFBZSxFQUFFLEdBQUcsS0FBSztBQUFBLGNBQUssYUFBYTtBQUFBO0FBQUEsWUFBdUIsRUFBRTtBQUFBLFlBQ3BFLGlCQUFpQixvQkFDYixDQUFDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVyxHQUFHLEdBQUcsMkJBQTJCLE1BQU0sQ0FBQyxJQUNuRixDQUFDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVyxDQUFDO0FBQUEsVUFDbEQ7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sMkJBQTJCLENBQUMsZUFDdkMsNEJBQTRCLFVBQW9FO0FBRTNGLE1BQU0sWUFBWSxDQUFDLFNBQXlCLGVBQThDO0FBQy9GLGNBQU0sRUFBRSxRQUFRLFlBQVksSUFBSTtBQUNoQyxjQUFNLG9CQUFvQix5QkFBeUIsRUFBRSxHQUFHLFlBQVksWUFBWSxDQUFDO0FBQ2pGLFlBQUlDLEtBQUksT0FBTyxzQkFBc0I7QUFDbkMsVUFBQUQsZ0JBQWUsUUFBUSxpQkFBaUI7QUFBQSxRQUMxQztBQUNBLFlBQUksV0FBVyxjQUFjO0FBQzNCLGdCQUFNLElBQUksTUFBTSx1REFBdUQ7QUFBQSxRQUN6RSxPQUFPO0FBQ0wsa0JBQVEsUUFBUSxvQ0FBb0MsUUFBUSxpQkFBaUIsQ0FBQztBQUFBLFFBQ2hGO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQ3hKQSxNQVNNRSxpQkFrQkEsMEJBa0NPO0FBN0RiO0FBQUE7QUFBQTtBQUlBO0FBR0E7QUFFQSxNQUFNQSxrQkFBaUIsQ0FBQyxXQUF3QztBQUM5RCxZQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssV0FBVyxHQUFHO0FBQy9CLGdCQUFNLElBQUksTUFBTSxnQ0FBZ0M7QUFBQSxRQUNsRDtBQUVBLFlBQUksQ0FBQyxDQUFDLEtBQUssS0FBSyxJQUFJLEVBQUUsU0FBUyxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxHQUFHO0FBQ2pELGdCQUFNLElBQUksTUFBTSwrQ0FBK0M7QUFBQSxRQUNqRTtBQUVBLFlBQUksT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLEdBQUc7QUFDL0IsZ0JBQU0sSUFBSSxNQUFNLHVDQUF1QztBQUFBLFFBQ3pEO0FBRUEsWUFBSSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsTUFBTSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRztBQUMzQyxnQkFBTSxJQUFJLE1BQU0sbURBQW1EO0FBQUEsUUFDckU7QUFBQSxNQUNGO0FBRUEsTUFBTSwyQkFBMkIsQ0FBQyxXQUErQztBQUMvRSxjQUFNLGNBQWMsT0FBTyxDQUFDLEVBQUU7QUFFOUIsY0FBTSxXQUFXLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQztBQUVqQyxjQUFNLGFBQWEsVUFBVSxLQUFLLFdBQVcsSUFBSTtBQUVqRCxjQUFNLFdBQVcsT0FBTyxDQUFDLEVBQUU7QUFDM0IsY0FBTSxRQUFRLGNBQWMsU0FBUyxVQUFVLGFBQWEsQ0FBQztBQUM3RCxjQUFNLE9BQU8sY0FBYyxRQUFRLFVBQVUsQ0FBQyxRQUFRLEdBQUcsQ0FBQztBQUMxRCxjQUFNLFdBQVcsY0FBYyxZQUFZLFVBQVUsYUFBYSxDQUFDO0FBQ25FLGNBQU0sU0FBUyxlQUFlLFVBQVUsVUFBVSxhQUFhLENBQUM7QUFFaEUsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFBQSxxQkFDckMsUUFBUTtBQUFBLElBQ3pCLGFBQWEsaUJBQWlCLE9BQU8sTUFBTSxVQUFVLE1BQU0sQ0FBQztBQUFBO0FBQUEsSUFFNUQsYUFBYSxVQUFVLENBQUM7QUFBQSxNQUN0QixhQUFhLHNDQUFzQyxVQUFVLENBQUM7QUFBQSxrQkFDbEQsTUFBTSxZQUFZLFlBQVksQ0FBQztBQUFBLFVBQ3ZDLEtBQUssWUFBWSx1QkFBdUIsQ0FBQyxNQUFNLFNBQVMsWUFBWSxZQUFZLENBQUM7QUFBQSxNQUNyRixPQUFPLFlBQVksY0FBYyxPQUFPLENBQUM7QUFBQTtBQUc3QyxlQUFPO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxPQUFPLENBQUMsRUFBRSxTQUFTLENBQUM7QUFBQSxZQUM3RCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxhQUFhO0FBQUE7QUFBQSxZQUF1QixFQUFFO0FBQUEsVUFDdEU7QUFBQSxVQUNBO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLFVBQVUsQ0FBQyxZQUFrQztBQUN4RCxRQUFBQSxnQkFBZSxRQUFRLE1BQU07QUFDN0IsZ0JBQVEsUUFBUSx5QkFBeUIsUUFBUSxNQUFNLENBQUM7QUFBQSxNQUMxRDtBQUFBO0FBQUE7OztBQ2hFQSxNQXNCTSxnQ0FzQ0EsOEJBd0NPLEtBSUEsTUFJQSxPQUlBLE1BSUEsT0FJQSxNQUdBLE9BU0EscUJBR0EsTUErQlAsa0NBc0JPLE1Bd0JBLE1BSUEsS0FJQSxNQVFBLHNCQUdBLEtBc0JBLFNBY0EsS0FLQSxLQUlBLE9BSUEsTUFZQSxXQWFBLEtBSUEsS0FJQSxZQUlBLE1BV0EsU0FTQSw0QkFRQSxhQWNBLEtBSUEsTUFJQSxNQUlBLEtBSUEsZ0JBRUEsTUFLQSxjQVVBLG9CQUdBLFVBY0EsaUJBY0EsS0FJQSxlQW1CQSxxQkFFQTtBQWhjYjtBQUFBO0FBQUE7QUFHQTtBQUVBO0FBQ0E7QUFHQTtBQWFBLE1BQU0saUNBQWlDLENBQ3JDLGNBQ0EsVUFDQSxlQUNBLGdCQUNBLFVBQ0EsMEJBQ0EsMkJBQ1c7QUFDWCxjQUFNLFVBQVUsS0FBSyxLQUFLLFdBQVcsQ0FBQztBQUV0QyxZQUFJLGFBQWE7QUFDakIsWUFBSSxPQUFPLGFBQWEsVUFBVTtBQUNoQyx1QkFBYSxHQUFHLFFBQVE7QUFBQSxRQUMxQixPQUFPO0FBQ0wsdUJBQWEsU0FBUyxHQUFHO0FBQUEsUUFDM0I7QUFFQSxjQUFNLFFBQVEsY0FBYyxhQUFhLGVBQWUsQ0FBQyxPQUFPLEdBQUcsQ0FBQztBQUNwRSxjQUFNLFNBQVMsZUFBZSxjQUFjLGdCQUFnQixDQUFDLE9BQU8sR0FBRyxDQUFDO0FBQ3hFLGNBQU0sV0FBOEIsQ0FBQyxFQUFFLE1BQU0sWUFBWSxNQUFNLE1BQU0sQ0FBQztBQUN0RSxZQUFJLHdCQUF3QjtBQUMxQixtQkFBUyxLQUFLLEdBQUcsc0JBQXNCO0FBQUEsUUFDekM7QUFFQSxlQUFPO0FBQUEsUUFDRCxhQUFhLGlCQUFpQixRQUFRLEVBQUUsaUJBQWlCLE9BQU8sTUFBTSxDQUFDO0FBQUE7QUFBQSxJQUUzRSw0QkFBNEIsRUFBRTtBQUFBO0FBQUEsSUFFOUIsYUFBYSxVQUFVLENBQUM7QUFBQSxNQUN0QixhQUFhLHNDQUFzQyxtQkFBbUIsQ0FBQztBQUFBO0FBQUEsY0FFL0QsTUFBTSxZQUFZLFlBQVksQ0FBQztBQUFBLE1BQ3ZDLE9BQU8sWUFBWSxjQUFjLFVBQVUsQ0FBQztBQUFBO0FBQUEsTUFFbEQ7QUFFQSxNQUFNLCtCQUErQixDQUNuQyxPQUNBLE1BQ0EsVUFDQSwwQkFDQSxVQUNBLGlCQUF5QixNQUFNLFVBQy9CLG9CQUNBLDJCQUNnQjtBQUNoQixjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sS0FBSyxLQUFLLFVBQVUsS0FBSyxNQUFNLElBQUksSUFBSSxDQUFDLEVBQUU7QUFBQSxRQUMzRTtBQUNBLFlBQUksb0JBQW9CO0FBQ3RCLDBCQUFnQixLQUFLLEdBQUcsa0JBQWtCO0FBQUEsUUFDNUM7QUFFQSxlQUFPO0FBQUEsVUFDTDtBQUFBLFVBQ0EsYUFBYSxFQUFFLE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxNQUFNLEVBQUU7QUFBQSxVQUMzRCxpQkFBaUIsQ0FBQyxpQkFDaEI7QUFBQSxZQUNFO0FBQUEsWUFDQSxVQUFVLEtBQUssTUFBTSxJQUFJO0FBQUEsWUFDekIsTUFBTTtBQUFBLFlBQ047QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxVQUNGO0FBQUEsVUFDRixZQUFZLENBQUMsa0JBQWtCO0FBQUEsWUFDN0IsU0FBUyxDQUFDLEVBQUUsTUFBTSxNQUFNLE1BQU0sVUFBVSxlQUFlLENBQUM7QUFBQSxZQUN4RCxlQUFlO0FBQUEsY0FDYixHQUFHLEtBQUs7QUFBQSxnQkFBSyxVQUFVLEtBQUssYUFBYSxDQUFDLEVBQUUsSUFBSSxJQUFJLEtBQTBCO0FBQUE7QUFBQSxjQUFnQjtBQUFBLFlBQ2hHO0FBQUEsWUFDQTtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sTUFBTSxDQUFDLFlBQWtDO0FBQ3BELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsT0FBTyxLQUFLLENBQUM7QUFBQSxNQUMvRTtBQUVPLE1BQU0sT0FBTyxDQUFDLFlBQWtDO0FBQ3JELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsUUFBUSxNQUFNLENBQUM7QUFBQSxNQUNqRjtBQUVPLE1BQU0sUUFBUSxDQUFDLFlBQWtDO0FBQ3RELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsU0FBUyxPQUFPLENBQUM7QUFBQSxNQUNuRjtBQUVPLE1BQU0sT0FBTyxDQUFDLFlBQWtDO0FBQ3JELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsUUFBUSxNQUFNLENBQUM7QUFBQSxNQUNqRjtBQUVPLE1BQU0sUUFBUSxDQUFDLFlBQWtDO0FBQ3RELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsU0FBUyxPQUFPLENBQUM7QUFBQSxNQUNuRjtBQUVPLE1BQU0sT0FBTyxDQUFDLFlBQWtDO0FBQ3JELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsUUFBUSxNQUFNLENBQUM7QUFBQSxNQUNqRjtBQUNPLE1BQU0sUUFBUSxDQUFDLFlBQWtDO0FBQ3RELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsU0FBUyxPQUFPLENBQUM7QUFBQSxNQUNuRjtBQU9PLE1BQU0sc0JBQXNCLENBQUMsZUFDbEMsNEJBQTRCLFVBQTRCO0FBRW5ELE1BQU0sT0FBTyxDQUFDLFNBQXlCLGVBQXFDO0FBQ2pGLFlBQUk7QUFDSixnQkFBUSxXQUFXLElBQUk7QUFBQSxVQUNyQjtBQUNFLG1CQUFPO0FBQ1A7QUFBQSxVQUNGO0FBQ0UsbUJBQU87QUFDUDtBQUFBLFVBQ0Y7QUFDRSxtQkFBTztBQUNQO0FBQUEsVUFDRjtBQUNFLG1CQUFPO0FBQ1A7QUFBQSxVQUNGO0FBQ0UsbUJBQU87QUFDUDtBQUFBLFVBQ0Y7QUFDRSxrQkFBTSxJQUFJLFdBQVcsMEVBQTBFLFdBQVcsRUFBRSxFQUFFO0FBQUEsUUFDbEg7QUFDQSxnQkFBUTtBQUFBLFVBQ04sNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsUUFBUSxNQUFNLFFBQVcsV0FBVyxVQUFVLFdBQVcsRUFBRTtBQUFBLFFBQzdHO0FBQUEsTUFDRjtBQU9BLE1BQU0sbUNBQW1DLENBQUMsV0FBa0Q7QUFDMUYsWUFBSTtBQUNKLFlBQUk7QUFDSixjQUFNLFNBQVMsT0FBTyxVQUFVLEtBQUssT0FBTyxDQUFDLEVBQUUsU0FBUztBQUN4RCxjQUFNLFNBQVMsT0FBTyxVQUFVLEtBQUssT0FBTyxDQUFDLEVBQUUsU0FBUztBQUV4RCxnQkFBUSxPQUFPLENBQUMsRUFBRSxVQUFVO0FBQUEsVUFDMUI7QUFDRSxrQkFBTSxTQUFTLE9BQU8sQ0FBQyxFQUFFLGdCQUFnQixFQUFFLENBQUMsSUFBSTtBQUNoRCxrQkFBTSxTQUFTLE9BQU8sQ0FBQyxFQUFFLGdCQUFnQixFQUFFLENBQUMsSUFBSTtBQUNoRDtBQUFBLFVBQ0Y7QUFDRSxrQkFBTSxTQUFTLE9BQU8sQ0FBQyxFQUFFLGVBQWUsRUFBRSxDQUFDLElBQUk7QUFDL0Msa0JBQU0sU0FBUyxPQUFPLENBQUMsRUFBRSxlQUFlLEVBQUUsQ0FBQyxJQUFJO0FBQy9DO0FBQUEsVUFDRjtBQUNFLGtCQUFNLElBQUksTUFBTSxxQkFBcUI7QUFBQSxRQUN6QztBQUVBLGVBQU8sNEJBQTRCLEVBQUUsS0FBSyxJQUFJLENBQUM7QUFBQSxNQUNqRDtBQUVPLE1BQU0sT0FBTyxDQUFDLFNBQXlCLG1CQUF5QztBQUNyRixjQUFNLGFBQWEsaUJBQWlCLGlCQUFpQixpQ0FBaUMsUUFBUSxNQUFNO0FBQ3BHLGNBQU0sV0FBVywwQkFBMEIsUUFBUSxPQUFPLENBQUMsRUFBRSxRQUFRO0FBQ3JFLGdCQUFRO0FBQUEsVUFDTjtBQUFBLFlBQ0UsUUFBUSxPQUFPLENBQUM7QUFBQSxZQUNoQjtBQUFBLFlBQ0EsQ0FBQyxNQUFNLFNBQVMsQ0FBQyxVQUFVLFFBQVEseUJBQXlCLFFBQVE7QUFBQSxZQUNwRTtBQUFBLFlBQ0EsV0FBVztBQUFBLFlBQ1g7QUFBQSxZQUNBO0FBQUEsY0FDRSxFQUFFLE1BQU0sUUFBUSxPQUFPLENBQUMsRUFBRSxVQUFVLE1BQU0sV0FBVyxJQUFJO0FBQUEsY0FDekQsRUFBRSxNQUFNLFFBQVEsT0FBTyxDQUFDLEVBQUUsVUFBVSxNQUFNLFdBQVcsSUFBSTtBQUFBLFlBQzNEO0FBQUEsWUFDQTtBQUFBLGNBQ0UsRUFBRSxNQUFNLE9BQU8sTUFBTSxTQUFtQztBQUFBLGNBQ3hELEVBQUUsTUFBTSxPQUFPLE1BQU0sU0FBbUM7QUFBQSxZQUMxRDtBQUFBLFVBQ0Y7QUFBQSxVQUNBLEVBQUUsUUFBUSxDQUFDLENBQUMsRUFBRTtBQUFBLFFBQ2hCO0FBQUEsTUFDRjtBQUVPLE1BQU0sT0FBTyxDQUFDLFlBQWtDO0FBQ3JELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsUUFBUSxNQUFNLENBQUM7QUFBQSxNQUNqRjtBQUVPLE1BQU0sTUFBTSxDQUFDLFlBQWtDO0FBQ3BELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsT0FBTyxLQUFLLENBQUM7QUFBQSxNQUMvRTtBQUVPLE1BQU0sT0FBTyxDQUFDLFlBQWtDO0FBQ3JELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsUUFBUSxNQUFNLENBQUM7QUFBQSxNQUNqRjtBQU1PLE1BQU0sdUJBQXVCLENBQUMsZUFDbkMsNEJBQTRCLFVBQStCO0FBRXRELE1BQU0sTUFBTSxDQUFDLFNBQXlCLGVBQXNDO0FBQ2pGLGNBQU0sV0FBVywwQkFBMEIsUUFBUSxPQUFPLENBQUMsRUFBRSxRQUFRO0FBQ3JFLGdCQUFRO0FBQUEsVUFDTjtBQUFBLFlBQ0UsUUFBUSxPQUFPLENBQUM7QUFBQSxZQUNoQjtBQUFBLFlBQ0EsQ0FBQyxNQUFNLFlBQVksQ0FBQztBQUFBLFlBQ3BCO0FBQUEsdUJBQ2lCLFFBQVEsSUFBSSxXQUFXLEtBQUs7QUFBQTtBQUFBLGtCQUVqQyxRQUFRLFFBQVEsUUFBUTtBQUFBO0FBQUE7QUFBQTtBQUFBLHdCQUlsQixRQUFRLGNBQWMsUUFBUTtBQUFBO0FBQUE7QUFBQSxZQUdoRCxXQUFXO0FBQUEsVUFDYjtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxVQUFVLENBQUMsVUFBVSxVQUFVO0FBQUEsWUFDaEMsT0FBTztBQUFBLFlBQ1AsT0FBTztBQUFBLFlBQ1AsT0FBTztBQUFBLFlBQ1AsT0FBTztBQUFBLFlBQ1AsT0FBTztBQUFBLFlBQ1AsT0FBTztBQUFBO0FBQUEsc0JBRUcsT0FBTyxjQUFjLE9BQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQU0zQyxNQUFNLE1BQU0sQ0FBQyxZQUFrQztBQUNwRCxjQUFNLFdBQVcsMEJBQTBCLFFBQVEsT0FBTyxDQUFDLEVBQUUsUUFBUTtBQUNyRSxnQkFBUSxRQUFRLDZCQUE2QixRQUFRLE9BQU8sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLFlBQVksQ0FBQyxLQUFLLFFBQVEsUUFBUSxDQUFDLENBQUM7QUFBQSxNQUNwSDtBQUVPLE1BQU0sTUFBTSxDQUFDLFlBQWtDO0FBQ3BELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsT0FBTyxLQUFLLENBQUM7QUFBQSxNQUMvRTtBQUVPLE1BQU0sUUFBUSxDQUFDLFlBQWtDO0FBQ3RELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsU0FBUyxPQUFPLENBQUM7QUFBQSxNQUNuRjtBQUVPLE1BQU0sT0FBTyxDQUFDLFlBQWtDO0FBQ3JELGNBQU0sV0FBVywwQkFBMEIsUUFBUSxPQUFPLENBQUMsRUFBRSxRQUFRO0FBQ3JFLGdCQUFRO0FBQUEsVUFDTjtBQUFBLFlBQ0UsUUFBUSxPQUFPLENBQUM7QUFBQSxZQUNoQjtBQUFBLFlBQ0EsQ0FBQyxNQUFNLFNBQVMsQ0FBQyxzQkFBc0IsQ0FBQztBQUFBLFlBQ3hDLFFBQVEsUUFBUTtBQUFBLFVBQ2xCO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLFlBQVksQ0FBQyxTQUF5QixlQUFzQztBQUN2RixjQUFNLFdBQVcsMEJBQTBCLFFBQVEsT0FBTyxDQUFDLEVBQUUsUUFBUTtBQUNyRSxnQkFBUTtBQUFBLFVBQ047QUFBQSxZQUNFLFFBQVEsT0FBTyxDQUFDO0FBQUEsWUFDaEI7QUFBQSxZQUNBLENBQUMsTUFBTSw4QkFBOEIsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFlBQVksUUFBUTtBQUFBLFlBQ3RFLDZCQUE2QixRQUFRLElBQUksV0FBVyxLQUFLO0FBQUEsWUFDekQsV0FBVztBQUFBLFVBQ2I7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sTUFBTSxDQUFDLFlBQWtDO0FBQ3BELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQztBQUFBLE1BQ3hGO0FBRU8sTUFBTSxNQUFNLENBQUMsWUFBa0M7QUFDcEQsZ0JBQVEsUUFBUSw2QkFBNkIsUUFBUSxPQUFPLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQUEsTUFDeEY7QUFFTyxNQUFNLGFBQWEsQ0FBQyxZQUFrQztBQUMzRCxnQkFBUSxRQUFRLDZCQUE2QixRQUFRLE9BQU8sQ0FBQyxHQUFHLGNBQWMsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxFQUFFLENBQUM7QUFBQSxNQUNsRztBQUVPLE1BQU0sT0FBTyxDQUFDLFlBQWtDO0FBQ3JELGNBQU0sV0FBVywwQkFBMEIsUUFBUSxPQUFPLENBQUMsRUFBRSxRQUFRO0FBQ3JFLGdCQUFRO0FBQUEsVUFDTjtBQUFBLFlBQ0UsUUFBUSxPQUFPLENBQUM7QUFBQSxZQUNoQjtBQUFBLFlBQ0EsQ0FBQyxNQUFNLGVBQWUsUUFBUSxXQUFXLENBQUMsS0FBSyxDQUFDLFdBQVcsUUFBUTtBQUFBLFVBQ3JFO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLFVBQVUsQ0FBQyxZQUFrQztBQUN4RCxnQkFBUSxRQUFRLDZCQUE2QixRQUFRLE9BQU8sQ0FBQyxHQUFHLFdBQVcsQ0FBQyxNQUFNLHNCQUFzQixDQUFDLEtBQUssQ0FBQztBQUFBLE1BQ2pIO0FBT08sTUFBTSw2QkFBNkIsQ0FBQyxlQUN6QztBQUFBLFFBQ0U7QUFBQSxNQUlGO0FBRUssTUFBTSxjQUFjLENBQUMsU0FBeUIsZUFBNEM7QUFDL0YsY0FBTSxXQUFXLDBCQUEwQixRQUFRLE9BQU8sQ0FBQyxFQUFFLFFBQVE7QUFDckUsZ0JBQVE7QUFBQSxVQUNOO0FBQUEsWUFDRSxRQUFRLE9BQU8sQ0FBQztBQUFBLFlBQ2hCO0FBQUEsWUFDQSxDQUFDLE1BQ0MsWUFBWSxRQUFRLG9CQUFvQixRQUFRLFdBQVcsV0FBVyxLQUFLLE1BQU0sQ0FBQyxXQUFXLFFBQVEsS0FBSyxXQUFXLElBQUk7QUFBQSxZQUMzSDtBQUFBLFlBQ0EsV0FBVztBQUFBLFVBQ2I7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sTUFBTSxDQUFDLFlBQWtDO0FBQ3BELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsT0FBTyxLQUFLLENBQUM7QUFBQSxNQUMvRTtBQUVPLE1BQU0sT0FBTyxDQUFDLFlBQWtDO0FBQ3JELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsUUFBUSxNQUFNLENBQUM7QUFBQSxNQUNqRjtBQUVPLE1BQU0sT0FBTyxDQUFDLFlBQWtDO0FBQ3JELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsUUFBUSxNQUFNLENBQUM7QUFBQSxNQUNqRjtBQUVPLE1BQU0sTUFBTSxDQUFDLFlBQWtDO0FBQ3BELGdCQUFRLFFBQVEsNkJBQTZCLFFBQVEsT0FBTyxDQUFDLEdBQUcsT0FBTyxLQUFLLENBQUM7QUFBQSxNQUMvRTtBQUVPLE1BQU0saUJBQWlCLENBQUMsTUFBYyxRQUFRLENBQUMseUJBQXlCLENBQUMsMkJBQTJCLENBQUM7QUFFckcsTUFBTSxPQUFPLENBQUMsWUFBa0M7QUFFckQsZ0JBQVEsUUFBUSw2QkFBNkIsUUFBUSxPQUFPLENBQUMsR0FBRyxRQUFRLGNBQWMsQ0FBQztBQUFBLE1BQ3pGO0FBRU8sTUFBTSxlQUFlLENBQUMsVUFBVSxVQUFVO0FBQUEscUJBQzVCLE9BQU87QUFBQSxxQkFDUCxPQUFPO0FBQUEscUJBQ1AsT0FBTztBQUFBO0FBQUEsb0JBRVIsT0FBTyxjQUFjLE9BQU87QUFBQSxXQUNyQyxlQUFlLEdBQUcsQ0FBQztBQUFBO0FBQUE7QUFJdkIsTUFBTSxxQkFBcUIsQ0FBQyxNQUNqQyx1Q0FBdUMsQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsdUJBQXVCLENBQUM7QUFFeEYsTUFBTSxXQUFXLENBQUMsWUFBa0M7QUFDekQsY0FBTSxXQUFXLDBCQUEwQixRQUFRLE9BQU8sQ0FBQyxFQUFFLFFBQVE7QUFDckUsZ0JBQVE7QUFBQSxVQUNOO0FBQUEsWUFDRSxRQUFRLE9BQU8sQ0FBQztBQUFBLFlBQ2hCO0FBQUEsWUFDQTtBQUFBLFlBQ0EsYUFBYSxRQUFRO0FBQUEsWUFDckI7QUFBQSxZQUNBLFFBQVEsT0FBTyxDQUFDLEVBQUU7QUFBQSxVQUNwQjtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxrQkFBa0IsQ0FBQyxTQUF5QixlQUF3QztBQUMvRixjQUFNLFdBQVcsMEJBQTBCLFFBQVEsT0FBTyxDQUFDLEVBQUUsUUFBUTtBQUNyRSxnQkFBUTtBQUFBLFVBQ047QUFBQSxZQUNFLFFBQVEsT0FBTyxDQUFDO0FBQUEsWUFDaEI7QUFBQSxZQUNBLENBQUMsTUFBTSxlQUFlLFFBQVEsV0FBVyxDQUFDLEtBQUssQ0FBQztBQUFBLFlBQ2hELHdDQUF3QyxRQUFRLEtBQUssV0FBVyxLQUFLO0FBQUEsWUFDckUsV0FBVztBQUFBLFVBQ2I7QUFBQSxRQUNGO0FBQ0EsZUFBTztBQUFBLE1BQ1Q7QUFFTyxNQUFNLE1BQU0sQ0FBQyxZQUFrQztBQUNwRCxnQkFBUSxRQUFRLDZCQUE2QixRQUFRLE9BQU8sQ0FBQyxHQUFHLE9BQU8sS0FBSyxDQUFDO0FBQUEsTUFDL0U7QUFFTyxNQUFNLGdCQUFnQixDQUFDLFNBQWlCLFVBQWtCO0FBQUEscUJBQzVDLE9BQU8sS0FBSyxLQUFLO0FBQUEsY0FDeEIsT0FBTztBQUFBLGVBQ04sT0FBTztBQUFBO0FBQUEsNkJBRU8sT0FBTyxjQUFjLE9BQU87QUFBQTtBQUFBLGtCQUV2QyxPQUFPO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFZbEIsTUFBTSxzQkFBc0IsQ0FBQyxNQUFjLG1CQUFtQixDQUFDO0FBRS9ELE1BQU0sWUFBWSxDQUFDLFNBQXlCLGVBQXNDO0FBQ3ZGLGNBQU0sUUFBUSwwQkFBMEIsUUFBUSxPQUFPLENBQUMsRUFBRSxRQUFRO0FBQ2xFLGdCQUFRO0FBQUEsVUFDTjtBQUFBLFlBQ0UsUUFBUSxPQUFPLENBQUM7QUFBQSxZQUNoQjtBQUFBLFlBQ0E7QUFBQSxZQUNBLGNBQWMsT0FBTyxXQUFXLEtBQUs7QUFBQSxZQUNyQyxXQUFXO0FBQUEsWUFDWCxRQUFRLE9BQU8sQ0FBQyxFQUFFO0FBQUEsVUFDcEI7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQzVjQSxNQVVNQyxpQkFrQkEsZ0NBeUNPO0FBckViO0FBQUE7QUFBQTtBQUlBO0FBR0E7QUFDQTtBQUVBLE1BQU1BLGtCQUFpQixDQUFDLFdBQXdDO0FBQzlELFlBQUksT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLEdBQUc7QUFDL0IsZ0JBQU0sSUFBSSxNQUFNLGdDQUFnQztBQUFBLFFBQ2xEO0FBRUEsWUFBSSxDQUFDLENBQUMsTUFBTSxNQUFNLEtBQUssRUFBRSxTQUFTLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLEdBQUc7QUFDcEQsZ0JBQU0sSUFBSSxNQUFNLDRDQUE0QztBQUFBLFFBQzlEO0FBRUEsWUFBSSxPQUFPLENBQUMsRUFBRSxLQUFLLFdBQVcsR0FBRztBQUMvQixnQkFBTSxJQUFJLE1BQU0sdUNBQXVDO0FBQUEsUUFDekQ7QUFFQSxZQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxNQUFNLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxHQUFHO0FBQzNDLGdCQUFNLElBQUksTUFBTSxtREFBbUQ7QUFBQSxRQUNyRTtBQUFBLE1BQ0Y7QUFFQSxNQUFNLGlDQUFpQyxDQUFDLFdBQStDO0FBQ3JGLGNBQU0sY0FBYyxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU07QUFDekMsb0JBQVksQ0FBQyxJQUFJLFlBQVksQ0FBQyxJQUFJO0FBRWxDLGNBQU0sUUFBUSxjQUFjLFNBQVMsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxNQUFNLENBQUM7QUFDMUUsY0FBTSxPQUFPLGNBQWMsUUFBUSxPQUFPLENBQUMsRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDO0FBQzdFLGNBQU0sU0FBUyxlQUFlLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxhQUFhLENBQUM7QUFFMUUsY0FBTSxhQUFhLFVBQVUsS0FBSyxXQUFXLElBQUk7QUFDakQsY0FBTSxXQUFXLDRCQUE0QixPQUFPLENBQUMsRUFBRSxRQUFRO0FBRS9ELGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQUE7QUFBQSx5QkFFakMsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDO0FBQUE7QUFBQSxJQUU5QyxhQUFhLGlCQUFpQixPQUFPLE1BQU0sTUFBTSxDQUFDO0FBQUE7QUFBQSxJQUVsRCxRQUFRLFFBQVEsQ0FBQztBQUFBO0FBQUEsSUFFakIsYUFBYSxVQUFVLENBQUM7QUFBQSxNQUN0QixhQUFhLHNDQUFzQyxVQUFVLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE1BUTlELE9BQU8sWUFBWSxjQUFjLHVCQUF1QixDQUFDO0FBQUE7QUFHN0QsZUFBTztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sWUFBWSxPQUFPO0FBQUEsWUFDakIsU0FBUyxDQUFDLEVBQUUsTUFBTSxhQUFhLFVBQVUsT0FBTyxDQUFDLEVBQUUsU0FBUyxDQUFDO0FBQUEsWUFDN0QsZUFBZSxFQUFFLEdBQUcsS0FBSztBQUFBLGNBQUssYUFBYTtBQUFBO0FBQUEsWUFBdUIsRUFBRTtBQUFBLFVBQ3RFO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxnQkFBZ0IsQ0FBQyxZQUFrQztBQUM5RCxRQUFBQSxnQkFBZSxRQUFRLE1BQU07QUFDN0IsZ0JBQVEsUUFBUSwrQkFBK0IsUUFBUSxNQUFNLENBQUM7QUFBQSxNQUNoRTtBQUFBO0FBQUE7OztBQ3hFQSxNQW9CTSw2QkFvSEEsMkJBMEZBLGFBcUJPLEtBSUEsS0FJQSxPQVdBLEtBSUEsS0F3QkEsS0FJQSxTQVdBLE1BV0EsZ0JBV0E7QUEzVWI7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUdBO0FBWUEsTUFBTSw4QkFBOEIsQ0FDbEMsY0FDQSxPQUNBLE9BQ0EsWUFDQSxXQUNBLGFBQ0EsNkJBQ0EsVUFDQSxPQUNBLE9BQ0EsWUFDQSw2QkFDRztBQUNILFlBQUk7QUFDSixZQUFJO0FBQ0osWUFBSSxPQUFPLGFBQWEsVUFBVTtBQUNoQyw2QkFBbUIsbUJBQW1CLENBQUNDLElBQUdDLE9BQU0sR0FBRyxRQUFRLEtBQUtELEVBQUMsTUFBTUMsRUFBQztBQUFBLFFBQzFFLFdBQVcsT0FBTyxhQUFhLFlBQVk7QUFDekMsNkJBQW1CLG1CQUFtQjtBQUFBLFFBQ3hDLE9BQU87QUFDTCw2QkFBbUIsU0FBUztBQUM1Qiw2QkFBbUIsU0FBUztBQUFBLFFBQzlCO0FBRUEsY0FBTSxTQUFTLGVBQWUsY0FBYyxZQUFZLFdBQVcsUUFBUSxDQUFDO0FBQzVFLGNBQU0sSUFBSSxjQUFjLFNBQVMsT0FBTyxNQUFNLFFBQVEsQ0FBQztBQUN2RCxjQUFNLElBQUksY0FBYyxTQUFTLE9BQU8sTUFBTSxRQUFRLENBQUM7QUFFdkQsWUFBSTtBQUNKLFlBQUksV0FBVztBQUNiLGNBQUksYUFBYTtBQUNmLGtCQUFNLGdCQUFnQixVQUFVLEtBQUssS0FBSyxNQUFNO0FBQ2hELGtCQUFNLGdCQUFnQixVQUFVLEtBQUssS0FBSyxNQUFNO0FBQ2hELGtCQUFNLHVCQUF1QixNQUFNLFNBQVMsS0FBSyxNQUFNLE1BQU0sU0FBUyxDQUFDLElBQUksTUFBTTtBQUNqRixrQkFBTSx1QkFBdUIsTUFBTSxTQUFTLEtBQUssTUFBTSxNQUFNLFNBQVMsQ0FBQyxJQUFJLE1BQU07QUFDakYsZ0JBQUksaUJBQWlCLGVBQWU7QUFDbEMsMkJBQWEsT0FBTztBQUFBLGdCQUNsQjtBQUFBLGdCQUNBO0FBQUEsa0JBQ0UsZ0JBQWdCLEdBQUcsRUFBRSxLQUFLLEtBQUssSUFBSSxFQUFFLFlBQVksR0FBRyxDQUFDLFFBQVEsRUFBRSxZQUFZLFlBQVk7QUFBQSxrQkFDdkYsZ0JBQWdCLEdBQUcsRUFBRSxLQUFLLEtBQUssSUFBSSxFQUFFLFlBQVksR0FBRyxDQUFDLFFBQVEsRUFBRSxZQUFZLFlBQVk7QUFBQSxnQkFDekY7QUFBQSxjQUNGO0FBQUEsWUFDRixPQUFPO0FBQ0wsMkJBQWE7QUFBQSxrQ0FDYSxPQUFPLGdCQUFnQixpQkFBaUIsQ0FBQztBQUFBLDRCQUMvQyxFQUFFLDJCQUEyQixpQkFBaUIsTUFBTSxDQUFDO0FBQUEsNEJBQ3JELEVBQUUsMkJBQTJCLGlCQUFpQixNQUFNLENBQUM7QUFBQSxjQUNuRSxPQUFPO0FBQUEsZ0JBQ1A7QUFBQSxnQkFDQTtBQUFBLGtCQUNFLCtCQUErQix1QkFDM0IsRUFBRSxZQUFZLGNBQWMsSUFDNUIsR0FBRyxFQUFFLEtBQUssS0FBSyxJQUFJLEVBQUUsWUFBWSxjQUFjLENBQUM7QUFBQSxrQkFDcEQsK0JBQStCLHVCQUMzQixFQUFFLFlBQVksY0FBYyxJQUM1QixHQUFHLEVBQUUsS0FBSyxLQUFLLElBQUksRUFBRSxZQUFZLGNBQWMsQ0FBQztBQUFBLGdCQUN0RDtBQUFBLGNBQ0YsQ0FBQztBQUFBO0FBQUEsWUFFUDtBQUFBLFVBQ0YsT0FBTztBQUNMLHlCQUFhLE9BQU87QUFBQSxjQUNsQjtBQUFBLGNBQ0EsaUJBQWlCLEVBQUUsWUFBWSxZQUFZLEdBQUcsRUFBRSxZQUFZLFlBQVksQ0FBQztBQUFBLFlBQzNFO0FBQUEsVUFDRjtBQUFBLFFBQ0YsT0FBTztBQUNMLGNBQUksQ0FBQyxhQUFhO0FBQ2hCLGtCQUFNLElBQUksTUFBTSxzRkFBc0Y7QUFBQSxVQUN4RztBQUVBLGdCQUFNLG1CQUFtQixDQUFDLFFBQWdCLEdBQVcsV0FBVyxPQUFPO0FBQ3JFLGtCQUFNLGNBQWMsZUFBZSxDQUFDLGVBQWUsQ0FBQztBQUNwRCxrQkFBTSxjQUFjLGVBQWUsQ0FBQyxlQUFlLENBQUM7QUFDcEQsbUJBQU87QUFBQSwrQkFDa0IsQ0FBQyxNQUFNLE9BQU8sZ0JBQWdCLHFCQUFxQixDQUFDLEdBQUcsQ0FBQztBQUFBLHlCQUM5RCxDQUFDLE1BQU0sRUFBRSwyQkFBMkIsZ0JBQWdCLENBQUMsSUFBSSxNQUFNLENBQUM7QUFBQSx5QkFDaEUsQ0FBQyxNQUFNLEVBQUUsMkJBQTJCLGdCQUFnQixDQUFDLElBQUksTUFBTSxDQUFDO0FBQUEsd0JBQ2pFLENBQUMsYUFBYSxDQUFDO0FBQUEsd0JBQ2YsQ0FBQyxhQUFhLENBQUM7QUFBQSw0QkFDWCxDQUFDLGFBQWEsQ0FBQztBQUFBLDRCQUNmLENBQUMsYUFBYSxDQUFDO0FBQUEsY0FDN0IsTUFBTSxJQUFJLENBQUMsT0FBTyxRQUFRLElBQUksaUJBQWlCLGFBQWEsV0FBVyxDQUFDO0FBQUE7QUFBQSxVQUVsRjtBQUNBLGNBQUksNkJBQThCO0FBQ2hDLHlCQUFhO0FBQUE7QUFBQSxjQUVMLGlCQUFpQixRQUFRLEdBQUcsS0FBSyxDQUFDO0FBQUEsY0FDbEMsaUJBQWlCLFFBQVEsR0FBRyxLQUFLLENBQUM7QUFBQSxjQUNsQyxpQkFBaUIsUUFBUSxHQUFHLEtBQUssQ0FBQztBQUFBLGNBQ2xDLGlCQUFpQixRQUFRLEdBQUcsS0FBSyxDQUFDO0FBQUE7QUFBQSxVQUU1QyxPQUFPO0FBQ0wseUJBQWE7QUFBQSxjQUNMLGlCQUFpQiwwQkFBMEIsQ0FBQyxDQUFDO0FBQUEsY0FDN0MsaUJBQWlCLDBCQUEwQixDQUFDLENBQUM7QUFBQSxjQUM3QyxpQkFBaUIsMEJBQTBCLENBQUMsQ0FBQztBQUFBLGNBQzdDLGlCQUFpQiwwQkFBMEIsQ0FBQyxDQUFDO0FBQUE7QUFBQSxVQUV2RDtBQUFBLFFBQ0Y7QUFFQSxlQUFPO0FBQUEsVUFDQyxhQUFhLGdCQUFnQixZQUFZLEtBQUssRUFBRSxpQkFBaUIsR0FBRyxHQUFHLE1BQU0sQ0FBQztBQUFBO0FBQUEsVUFFOUUsNEJBQTRCLEVBQUU7QUFBQTtBQUFBLFVBRTlCLGFBQWEsVUFBVSxDQUFDO0FBQUEsVUFDeEIsYUFBYSxzQ0FBc0MsbUJBQW1CLENBQUM7QUFBQSxVQUN2RSxVQUFVO0FBQUE7QUFBQSxNQUVwQjtBQUVBLE1BQU0sNEJBQTRCLENBQ2hDLE1BQ0EsVUFDQSxHQUNBLEdBQ0EsVUFDQSwwQkFDQSxpQkFBeUIsRUFBRSxhQUNYO0FBQ2hCLGNBQU0sUUFBUSxFQUFFLEtBQUssSUFBSSxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssQ0FBQztBQUM5QyxjQUFNLFFBQVEsRUFBRSxLQUFLLElBQUksQ0FBQyxNQUFNLE9BQU8sQ0FBQyxLQUFLLENBQUM7QUFDOUMsY0FBTSxjQUFjLENBQUMsVUFBVSxTQUFTLE9BQU8sS0FBSztBQUNwRCxZQUFJLGNBQWM7QUFDbEIsWUFBSSxhQUFhLFVBQVUsS0FBSyxLQUFLO0FBRXJDLFlBQUksWUFBWTtBQUNoQixZQUFJLDhCQUE4QjtBQUdsQyxjQUFNLGNBQWMsQ0FBQyxXQUFXO0FBQ2hDLFlBQUksYUFBYTtBQUNmLGdCQUFNLGtCQUFrQixjQUFjLFVBQVUsT0FBTyxPQUFPLEtBQUs7QUFDbkUsY0FBSSxDQUFDLGlCQUFpQjtBQUNwQixrQkFBTSxJQUFJLE1BQU0sOENBQThDO0FBQUEsVUFDaEU7QUFDQSx3QkFBYyxnQkFBZ0IsTUFBTTtBQUNwQyx1QkFBYSxVQUFVLEtBQUssV0FBVztBQUN2QyxnQkFBTSxnQkFBZ0IsVUFBVSxLQUFLLEtBQUssTUFBTTtBQUNoRCxnQkFBTSxnQkFBZ0IsVUFBVSxLQUFLLEtBQUssTUFBTTtBQUNoRCxnQkFBTSx1QkFBdUIsTUFBTSxTQUFTLEtBQUssTUFBTSxNQUFNLFNBQVMsQ0FBQyxJQUFJLE1BQU07QUFDakYsZ0JBQU0sdUJBQXVCLE1BQU0sU0FBUyxLQUFLLE1BQU0sTUFBTSxTQUFTLENBQUMsSUFBSSxNQUFNO0FBQ2pGLHNCQUFZLEtBQUssYUFBYTtBQUM5QixzQkFBWSxLQUFLLGFBQWE7QUFDOUIsc0JBQVksS0FBSyxvQkFBb0I7QUFDckMsc0JBQVksS0FBSyxvQkFBb0I7QUFFckMsY0FBSSxrQkFBa0I7QUFDdEIsbUJBQVMsSUFBSSxHQUFHLElBQUksWUFBWSxRQUFRLEtBQUs7QUFDM0Msa0JBQU0sT0FBTyxNQUFNLE1BQU0sU0FBUyxDQUFDO0FBQ25DLGtCQUFNLE9BQU8sTUFBTSxNQUFNLFNBQVMsQ0FBQztBQUNuQyxnQkFBSSxTQUFTLE1BQU07QUFDakIsaUNBQW1CO0FBQUEsWUFDckIsT0FBTztBQUNMO0FBQUEsWUFDRjtBQUFBLFVBQ0Y7QUFDQSxjQUFJLGtCQUFrQixNQUFNLEdBQUc7QUFDN0IsMENBQThCO0FBQzlCLHdCQUFZO0FBQUEsVUFDZCxXQUFXLGlCQUFpQixpQkFBaUIsd0JBQXdCLHNCQUFzQjtBQUN6Rix3QkFBWTtBQUFBLFVBQ2Q7QUFBQSxRQUNGLE9BQU87QUFFTCxzQkFBWTtBQUFBLFFBQ2Q7QUFDQSxvQkFBWSxLQUFLLFNBQVM7QUFFMUIsZUFBTztBQUFBLFVBQ0w7QUFBQSxVQUNBLGFBQWE7QUFBQSxZQUNYLE1BQU0sV0FBVyxZQUFZLElBQUksQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLEVBQUUsS0FBSyxHQUFHO0FBQUEsWUFDOUQsbUJBQW1CLENBQUMsUUFBUSxNQUFNO0FBQUEsVUFDcEM7QUFBQSxVQUNBLGlCQUFpQixDQUFDLGlCQUNoQjtBQUFBLFlBQ0U7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQSxFQUFFO0FBQUEsWUFDRixFQUFFO0FBQUEsWUFDRjtBQUFBLFlBQ0E7QUFBQSxVQUNGO0FBQUEsVUFDRixZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxlQUFlLENBQUM7QUFBQSxZQUN6RCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxhQUFhLEtBQTBCO0FBQUE7QUFBQSxZQUFzQixFQUFFO0FBQUEsWUFDN0YsaUJBQWlCO0FBQUEsY0FDZixFQUFFLHVCQUF1QixNQUFNLEtBQUssS0FBSyxVQUFVLEtBQUssV0FBVyxJQUFJLENBQUMsRUFBRTtBQUFBLGNBQzFFLEdBQUcsMkJBQTJCLE9BQU8sT0FBTyxXQUFXO0FBQUEsWUFDekQ7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFQSxNQUFNLGNBQWMsQ0FDbEIsU0FDQSxNQUNBLFVBQ0EsMEJBQ0EsVUFDQSxtQkFDUztBQUNULGdCQUFRO0FBQUEsVUFDTjtBQUFBLFlBQ0U7QUFBQSxZQUNBLFlBQVk7QUFBQSxZQUNaLFFBQVEsT0FBTyxDQUFDO0FBQUEsWUFDaEIsUUFBUSxPQUFPLENBQUM7QUFBQSxZQUNoQjtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxNQUFNLENBQUMsWUFBa0M7QUFDcEQsb0JBQVksU0FBUyxPQUFPLENBQUMsR0FBRyxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRTtBQUFBLE1BQ25EO0FBRU8sTUFBTSxNQUFNLENBQUMsWUFBa0M7QUFDcEQsb0JBQVksU0FBUyxPQUFPLENBQUMsR0FBRyxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRTtBQUFBLE1BQ25EO0FBRU8sTUFBTSxRQUFRLENBQUMsWUFBa0M7QUFDdEQ7QUFBQSxVQUNFO0FBQUEsVUFDQTtBQUFBLFVBQ0EsRUFBRSxRQUFRLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxRQUFRLENBQUMsR0FBRyxNQUFNLGFBQWEsQ0FBQyxLQUFLLENBQUMsSUFBSTtBQUFBLFVBQ2pGO0FBQUEsVUFDQTtBQUFBO0FBQUEsUUFFRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLE1BQU0sQ0FBQyxZQUFrQztBQUNwRCxvQkFBWSxTQUFTLE9BQU8sQ0FBQyxHQUFHLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFO0FBQUEsTUFDbkQ7QUFFTyxNQUFNLE1BQU0sQ0FBQyxZQUFrQztBQUNwRCxjQUFNLE9BQU8sY0FBYyxTQUFTLFFBQVEsT0FBTyxDQUFDLEVBQUUsVUFBVSxRQUFRLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxLQUFLO0FBQzdGLGNBQU0sV0FBVyxTQUFTLFFBQVEsVUFBVTtBQUM1QztBQUFBLFVBQ0U7QUFBQSxVQUNBO0FBQUEsVUFDQSxFQUFFLFFBQVEsQ0FBQyxHQUFHLE1BQU0sY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLFFBQVEsQ0FBQyxHQUFHLE1BQU0scUJBQXFCLENBQUMsSUFBSSxDQUFDLElBQUk7QUFBQSxVQUM5RjtBQUFBLHdCQUNvQixJQUFJLFNBQVMsSUFBSSxRQUFRLElBQUk7QUFBQSxpQkFDcEMsSUFBSTtBQUFBLGlCQUNKLElBQUk7QUFBQSx1QkFDRSxJQUFJO0FBQUEsaUJBQ1YsSUFBSTtBQUFBO0FBQUEsK0JBRVUsSUFBSSw2QkFBNkIsSUFBSSxxQkFBcUIsSUFBSSxJQUFJLFFBQVE7QUFBQTtBQUFBLG9DQUVyRSxJQUFJLGVBQWUsSUFBSSxjQUFjLElBQUk7QUFBQTtBQUFBLG9CQUV6RCxJQUFJO0FBQUE7QUFBQTtBQUFBLFFBR3RCO0FBQUEsTUFDRjtBQUVPLE1BQU0sTUFBTSxDQUFDLFlBQWtDO0FBQ3BELG9CQUFZLFNBQVMsT0FBTyxDQUFDLEdBQUcsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUU7QUFBQSxNQUNuRDtBQUVPLE1BQU0sVUFBVSxDQUFDLFlBQWtDO0FBQ3hEO0FBQUEsVUFDRTtBQUFBLFVBQ0E7QUFBQSxVQUNBLEVBQUUsUUFBUSxDQUFDLEdBQUcsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssUUFBUSxDQUFDLEdBQUcsTUFBTSxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUk7QUFBQSxVQUMvRTtBQUFBLFVBQ0E7QUFBQTtBQUFBLFFBRUY7QUFBQSxNQUNGO0FBRU8sTUFBTSxPQUFPLENBQUMsWUFBa0M7QUFDckQ7QUFBQSxVQUNFO0FBQUEsVUFDQTtBQUFBLFVBQ0EsRUFBRSxRQUFRLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxRQUFRLENBQUMsR0FBRyxNQUFNLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSTtBQUFBLFVBQy9FO0FBQUEsVUFDQTtBQUFBO0FBQUEsUUFFRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLGlCQUFpQixDQUFDLFlBQWtDO0FBQy9EO0FBQUEsVUFDRTtBQUFBLFVBQ0E7QUFBQSxVQUNBLEVBQUUsUUFBUSxDQUFDLEdBQUcsTUFBTSxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssUUFBUSxDQUFDLEdBQUcsTUFBTSxhQUFhLENBQUMsS0FBSyxDQUFDLElBQUk7QUFBQSxVQUNqRjtBQUFBLFVBQ0E7QUFBQTtBQUFBLFFBRUY7QUFBQSxNQUNGO0FBRU8sTUFBTSxjQUFjLENBQUMsWUFBa0M7QUFDNUQ7QUFBQSxVQUNFO0FBQUEsVUFDQTtBQUFBLFVBQ0EsRUFBRSxRQUFRLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxRQUFRLENBQUMsR0FBRyxNQUFNLGFBQWEsQ0FBQyxLQUFLLENBQUMsSUFBSTtBQUFBLFVBQ2pGO0FBQUEsVUFDQTtBQUFBO0FBQUEsUUFFRjtBQUFBLE1BQ0Y7QUFBQTtBQUFBOzs7QUNwVkEsTUFlTUMsaUJBNEJBLHlCQVdBLGtCQW1CQSx5QkF1RU8sUUFpQkE7QUFqS2I7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUNBO0FBR0E7QUFNQSxNQUFNQSxrQkFBaUIsQ0FBQyxRQUErQixTQUF1QjtBQUM1RSxZQUFJLENBQUMsVUFBVSxPQUFPLFNBQVMsR0FBRztBQUNoQyxnQkFBTSxJQUFJLE1BQU0sZ0JBQWdCO0FBQUEsUUFDbEM7QUFDQSxjQUFNLGlCQUFpQjtBQUN2QixjQUFNLGlCQUFpQixPQUFPLGNBQWM7QUFDNUMsY0FBTSxZQUFZLGVBQWU7QUFDakMsY0FBTSxZQUFZLGVBQWUsS0FBSztBQUN0QyxlQUFPLFFBQVEsQ0FBQyxPQUFPLE1BQU07QUFDM0IsY0FBSSxNQUFNLGdCQUFnQjtBQUN4QjtBQUFBLFVBQ0Y7QUFFQSxjQUFJLE1BQU0sYUFBYSxXQUFXO0FBQ2hDLGtCQUFNLElBQUksTUFBTSxrQ0FBa0M7QUFBQSxVQUNwRDtBQUVBLGNBQUksTUFBTSxLQUFLLFdBQVcsV0FBVztBQUNuQyxrQkFBTSxJQUFJLE1BQU0sMENBQTBDO0FBQUEsVUFDNUQ7QUFDQSxnQkFBTSxLQUFLLFFBQVEsQ0FBQyxLQUFLQyxPQUFNO0FBQzdCLGdCQUFJQSxPQUFNLFFBQVEsUUFBUSxlQUFlLEtBQUtBLEVBQUMsR0FBRztBQUNoRCxvQkFBTSxJQUFJLE1BQU0sa0NBQWtDO0FBQUEsWUFDcEQ7QUFBQSxVQUNGLENBQUM7QUFBQSxRQUNILENBQUM7QUFBQSxNQUNIO0FBRUEsTUFBTSwwQkFBMEIsQ0FBQyxpQkFBeUIsd0JBQXdDO0FBQUE7QUFBQSx3Q0FFMUQsZUFBZSxNQUFNLG1CQUFtQjtBQUFBLGdDQUNoRCxlQUFlO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxhQUtsQyxlQUFlO0FBQUE7QUFHNUIsTUFBTSxtQkFBbUIsQ0FBQyxRQUFrQyxXQUEwQjtBQUNwRixjQUFNLGtCQUFrQixPQUFPO0FBRS9CLGNBQU0sWUFBc0IsQ0FBQztBQUM3QixpQkFBUyxJQUFJLEdBQUcsSUFBSSxpQkFBaUIsRUFBRSxHQUFHO0FBQ3hDLGdCQUFNLGdCQUFnQixPQUFPLFlBQVksY0FBYyxPQUFPLENBQUMsRUFBRSxhQUFhLFNBQVMsQ0FBQztBQUN4RixjQUFJLG9CQUFvQixHQUFHO0FBQ3pCLHNCQUFVLEtBQUssYUFBYTtBQUFBLFVBQzlCLFdBQVcsTUFBTSxHQUFHO0FBQ2xCLHNCQUFVLEtBQUsscUJBQXFCLENBQUMsUUFBUSxhQUFhLElBQUk7QUFBQSxVQUNoRSxXQUFXLE1BQU0sa0JBQWtCLEdBQUc7QUFDcEMsc0JBQVUsS0FBSyxVQUFVLGFBQWEsSUFBSTtBQUFBLFVBQzVDLE9BQU87QUFDTCxzQkFBVSxLQUFLLDBCQUEwQixDQUFDLE9BQU8sYUFBYSxJQUFJO0FBQUEsVUFDcEU7QUFBQSxRQUNGO0FBQ0EsZUFBTyxVQUFVLEtBQUssSUFBSTtBQUFBLE1BQzVCO0FBRUEsTUFBTSwwQkFBMEIsQ0FDOUIsUUFDQSxjQUNBLGFBQ0EsYUFDZ0I7QUFDaEIsY0FBTSxhQUFhLFVBQVUsS0FBSyxXQUFXO0FBRTdDLGNBQU0sbUJBQW1CLElBQUksTUFBYyxPQUFPLE1BQU07QUFDeEQsY0FBTSxZQUFZLElBQUksTUFBcUIsT0FBTyxNQUFNO0FBRXhELFlBQUksY0FBYztBQUNsQixjQUFNLG9CQUF3RCxDQUFDO0FBQy9ELGNBQU0sYUFBYSxDQUFDO0FBQ3BCLGNBQU0sa0JBQW9DLENBQUMsRUFBRSx1QkFBdUIsTUFBTSxXQUFXLENBQUM7QUFDdEYsaUJBQVMsSUFBSSxHQUFHLElBQUksT0FBTyxRQUFRLEVBQUUsR0FBRztBQUN0Qyx5QkFBZSxPQUFPLENBQUMsRUFBRSxLQUFLLFlBQVk7QUFDMUMsMkJBQWlCLENBQUMsSUFBSTtBQUN0QixxQkFBVyxLQUFLLE9BQU8sQ0FBQyxFQUFFLEtBQUssTUFBTTtBQUNyQyxvQkFBVSxDQUFDLElBQUksY0FBYyxRQUFRLENBQUMsSUFBSSxVQUFVLFdBQVcsQ0FBQyxDQUFDO0FBQ2pFLDRCQUFrQixLQUFLLE1BQU07QUFDN0IsMEJBQWdCLEtBQUssRUFBRSx1QkFBdUIsTUFBTSxpQkFBaUIsQ0FBQyxFQUFFLENBQUM7QUFBQSxRQUMzRTtBQUNBLGlCQUFTLElBQUksR0FBRyxJQUFJLE9BQU8sUUFBUSxFQUFFLEdBQUc7QUFDdEMsMEJBQWdCLEtBQUssR0FBRywyQkFBMkIsT0FBTyxDQUFDLEVBQUUsSUFBSSxDQUFDO0FBQUEsUUFDcEU7QUFDQSx3QkFBZ0IsS0FBSyxHQUFHLDJCQUEyQixXQUFXLENBQUM7QUFFL0QsY0FBTSxTQUFTLGVBQWUsVUFBVSxVQUFVLFlBQVksTUFBTTtBQUNwRSxjQUFNLGNBQWMsT0FBTyxXQUFXLFdBQVcsWUFBWTtBQUM3RCxjQUFNLHNCQUFzQixNQUFNLEtBQUssTUFBTSxpQkFBaUIsTUFBTSxFQUFFLEtBQUssQ0FBQyxFQUN6RSxJQUFJLENBQUMsTUFBTSw0QkFBNEIsQ0FBQyxFQUFFLEVBQzFDLEtBQUssR0FBRztBQUNYLGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQUE7QUFBQSxLQUVyRCxNQUFNO0FBQ1AsdUJBQWEsZ0JBQWdCLGNBQWMsS0FBSztBQUNoRCxtQkFBUyxJQUFJLEdBQUcsSUFBSSxPQUFPLFFBQVEsS0FBSztBQUN0Qyx5QkFBYSxnQkFBZ0IsbUJBQW1CLENBQUMsSUFBSSxLQUFLO0FBQUEsVUFDNUQ7QUFDQSxpQkFBTyxhQUFhLGlCQUFpQixHQUFHLFdBQVcsTUFBTTtBQUFBLFFBQzNELEdBQUcsQ0FBQztBQUFBO0FBQUEsSUFFRix3QkFBd0IsaUJBQWlCLFFBQVEsbUJBQW1CLENBQUM7QUFBQTtBQUFBLElBRXJFLGFBQWEsVUFBVSxDQUFDO0FBQUEsTUFDdEIsYUFBYSxzQ0FBc0MscUJBQXFCLENBQUM7QUFBQTtBQUFBLG9CQUUzRCxPQUFPLGdCQUFnQixZQUFZLENBQUM7QUFBQTtBQUFBLDJDQUViLFdBQVc7QUFBQTtBQUFBLDBDQUVaLGlCQUFpQixNQUFNLE1BQU0sbUJBQW1CO0FBQUEsUUFDbEYsV0FBVztBQUFBO0FBQUE7QUFBQSxNQUdiLGlCQUFpQixXQUFXLE1BQU0sQ0FBQztBQUFBO0FBR3ZDLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWEsRUFBRSxNQUFNLEdBQUcsWUFBWSxJQUFJLGtCQUFrQjtBQUFBLFVBQzFELFlBQVksT0FBTztBQUFBLFlBQ2pCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sYUFBYSxTQUFTLENBQUM7QUFBQSxZQUN6QyxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxhQUFhO0FBQUE7QUFBQSxZQUF1QixFQUFFO0FBQUEsWUFDcEU7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxTQUFTLENBQUMsU0FBeUIsZUFBdUM7QUFDckYsY0FBTSxTQUFTLFFBQVE7QUFDdkIsY0FBTSxhQUFhLE9BQU8sQ0FBQyxFQUFFO0FBQzdCLGNBQU0sZUFBZSxVQUFVLGNBQWMsV0FBVyxNQUFNLFdBQVcsTUFBTTtBQUMvRSxRQUFBRCxnQkFBZSxRQUFRLFlBQVk7QUFDbkMsY0FBTSxjQUFjLFdBQVcsTUFBTTtBQUNyQyxvQkFBWSxZQUFZLElBQUksT0FBTztBQUFBLFVBQ2pDLENBQUMsS0FBSyxVQUFVLE9BQU8sTUFBTSxLQUFLLFNBQVMsZUFBZSxNQUFNLEtBQUssWUFBWSxJQUFJO0FBQUEsVUFDckY7QUFBQSxRQUNGO0FBRUEsY0FBTSxpQkFBaUIsT0FBTyxPQUFPLENBQUMsVUFBVSxVQUFVLEtBQUssTUFBTSxJQUFJLElBQUksQ0FBQztBQUM5RSxnQkFBUSxRQUFRLHdCQUF3QixnQkFBZ0IsY0FBYyxhQUFhLE9BQU8sQ0FBQyxFQUFFLFFBQVEsR0FBRztBQUFBLFVBQ3RHLFFBQVE7QUFBQSxRQUNWLENBQUM7QUFBQSxNQUNIO0FBRU8sTUFBTSx3QkFBd0IsQ0FBQyxlQUNwQyw0QkFBNEIsRUFBRSxNQUFNLFdBQVcsS0FBZSxDQUFDO0FBQUE7QUFBQTs7O0FDbEtqRSxNQWlCYSxzQkFnQ0EsOEJBbUJBLDBCQVVBO0FBOUViO0FBQUE7QUFBQTtBQUdBO0FBQ0E7QUFhTyxNQUFNLHVCQUF1QixDQUNsQyxZQUNBLFdBQ0EsV0FBVyxVQUNBO0FBQ1gsZ0JBQVEsV0FBVyxZQUFZO0FBQUEsVUFDN0IsS0FBSztBQUNILG1CQUFPLHNCQUFzQixTQUFTO0FBQUEsVUFDeEMsS0FBSztBQUNILG1CQUFPLFlBQVksU0FBUyxZQUFZLFNBQVM7QUFBQSxVQUNuRCxLQUFLO0FBQ0gsbUJBQU8sd0JBQXdCLFNBQVMsSUFBSSxRQUFRLHlCQUF5QixTQUFTLElBQ3BGLFFBQ0Y7QUFBQSxVQUNGLEtBQUs7QUFDSCxtQkFBTyxlQUFlLFNBQVMsY0FBYyxTQUFTLFVBQVUsUUFBUSw4QkFDdEUsUUFDRjtBQUFBLFVBQ0YsS0FBSztBQUNILG1CQUFPLGtCQUFrQixRQUFRLDZDQUE2QyxTQUFTO0FBQUEsVUFDekYsS0FBSztBQUNILG1CQUFPO0FBQUE7QUFBQTtBQUFBLFVBR1QsS0FBSztBQUNILG1CQUFPO0FBQUE7QUFBQSxVQUVUO0FBQ0Usa0JBQU0sSUFBSSxNQUFNLDBCQUEwQixXQUFXLFVBQVUsRUFBRTtBQUFBLFFBQ3JFO0FBQUEsTUFDRjtBQUVPLE1BQU0sK0JBQStCLENBQzFDLFlBQ0EsbUJBQ0c7QUFDSCxZQUFJLFdBQVcsZUFBZSxRQUFRO0FBQ3BDLHlCQUFlO0FBQUEsWUFDYixFQUFFLHFCQUFzQixNQUFNLFdBQVcsUUFBUztBQUFBLFlBQ2xELEVBQUUscUJBQXNCLE1BQU0sV0FBVyxRQUFTO0FBQUEsVUFDcEQ7QUFBQSxRQUNGLFdBQVcsV0FBVyxlQUFlLGVBQWU7QUFDbEQseUJBQWU7QUFBQSxZQUNiLEVBQUUscUJBQXNCLE1BQU0sV0FBVyxNQUFPO0FBQUEsWUFDaEQsRUFBRSxxQkFBc0IsTUFBTSxXQUFXLEtBQU07QUFBQSxVQUNqRDtBQUFBLFFBQ0YsV0FBVyxXQUFXLGVBQWUsYUFBYTtBQUNoRCx5QkFBZSxLQUFLLEVBQUUscUJBQXNCLE1BQU0sV0FBVyxNQUFPLENBQUM7QUFBQSxRQUN2RTtBQUFBLE1BQ0Y7QUFFTyxNQUFNLDJCQUEyQixDQUFDLFlBQTBDLGFBQWdDO0FBQ2pILFlBQUksV0FBVyxlQUFlLFFBQVE7QUFDcEMsbUJBQVMsS0FBSyxFQUFFLE1BQU0sWUFBWSxNQUFNLE1BQU0sR0FBRyxFQUFFLE1BQU0sWUFBWSxNQUFNLE1BQU0sQ0FBQztBQUFBLFFBQ3BGLFdBQVcsV0FBVyxlQUFlLGVBQWU7QUFDbEQsbUJBQVMsS0FBSyxFQUFFLE1BQU0sU0FBUyxNQUFNLE1BQU0sR0FBRyxFQUFFLE1BQU0sUUFBUSxNQUFNLE1BQU0sQ0FBQztBQUFBLFFBQzdFLFdBQVcsV0FBVyxlQUFlLGFBQWE7QUFDaEQsbUJBQVMsS0FBSyxFQUFFLE1BQU0sU0FBUyxNQUFNLE1BQU0sQ0FBQztBQUFBLFFBQzlDO0FBQUEsTUFDRjtBQUVPLE1BQU0sb0NBQW9DLENBQy9DLGVBQ2lDO0FBQ2pDLGNBQU0sYUFBYyxZQUFZLGNBQXlCO0FBQ3pELFlBQUksZUFBZSxlQUFlO0FBQ2hDLGdCQUFNLENBQUMsT0FBTyxJQUFJLElBQUssWUFBWSxxQkFBMEMsQ0FBQyxLQUFLLEdBQUc7QUFDdEYsaUJBQU8sRUFBRSxZQUFZLE9BQU8sS0FBSztBQUFBLFFBQ25DLFdBQVcsZUFBZSxRQUFRO0FBQ2hDLGdCQUFNLENBQUMsU0FBUyxPQUFPLElBQUssWUFBWSxxQkFBMEMsQ0FBQyxVQUFVLFFBQVE7QUFDckcsaUJBQU8sRUFBRSxZQUFZLFNBQVMsUUFBUTtBQUFBLFFBQ3hDLFdBQVcsZUFBZSxhQUFhO0FBQ3JDLGdCQUFNLENBQUMsS0FBSyxJQUFLLFlBQVkscUJBQWtDLENBQUMsSUFBSTtBQUNwRSxpQkFBTyxFQUFFLFlBQVksTUFBTTtBQUFBLFFBQzdCO0FBQ0EsZUFBTyxFQUFFLFdBQVc7QUFBQSxNQUN0QjtBQUFBO0FBQUE7OztBQzdGQSxNQXFCYSxhQWVBO0FBcENiO0FBQUE7QUFBQTtBQXFCTyxNQUFNLGNBQWMsQ0FBQyxXQUFtQixhQUFxQjtBQUNsRSxnQkFBUSxXQUFXO0FBQUEsVUFDakIsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFDVCxLQUFLO0FBQ0gsbUJBQU8sUUFBUSxRQUFRO0FBQUEsVUFDekIsS0FBSztBQUNILG1CQUFPLFFBQVEsUUFBUTtBQUFBLFVBQ3pCLEtBQUs7QUFDSCxtQkFBTyxRQUFRLFFBQVE7QUFBQSxVQUN6QjtBQUNFLGtCQUFNLElBQUksTUFBTSxHQUFHLFNBQVMsOEJBQThCO0FBQUEsUUFDOUQ7QUFBQSxNQUNGO0FBRU8sTUFBTSxjQUFjLENBQUMsWUFBNkI7QUFBQSxRQUNqRCxVQUFVLG1EQUFtRCxFQUFFO0FBQUE7QUFBQTtBQUFBOzs7QUNyQ3ZFLE1BcUJhO0FBckJiO0FBQUE7QUFBQTtBQXFCTyxNQUFNLGdCQUFnQixDQUFDLGNBQXNCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsVUFPMUMsU0FBUyxZQUFZLFNBQVMsWUFBWSxTQUFTO0FBQUE7QUFBQTtBQUFBO0FBQUE7OztBQzVCN0QsTUE2QmEsOENBd0JBO0FBckRiO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFHQTtBQVlBO0FBU08sTUFBTSwrQ0FBK0MsQ0FDMUQsbUJBQ0FFLGdCQUNBLGdCQUNBLGlCQUNBLHFCQUNHO0FBR0gsY0FBTSxxQkFBcUIsa0JBQWtCO0FBQzdDLGVBQU87QUFBQSxRQUNELE1BQU0sS0FBSyxFQUFFLFFBQVEsZUFBZSxDQUFDLEVBQ3BDO0FBQUEsVUFDQyxDQUFDLEdBQUcsTUFBTTtBQUFBLFlBQ1IsYUFBYUEsZUFBYyxPQUFPLEdBQUdBLGVBQWMsSUFBSSxDQUFDO0FBQUEsVUFDMURBLGVBQWMsV0FBVyxtQkFBbUIsR0FBRyxhQUFhLGtCQUFrQixJQUFJLG9CQUFvQixlQUFlLENBQUMsQ0FBQztBQUFBO0FBQUEsVUFFdkhBLGVBQWMsV0FBVyxtQkFBbUIsR0FBRyxDQUFDLENBQUM7QUFBQTtBQUFBLFFBRW5ELEVBQ0MsS0FBSyxFQUFFLENBQUM7QUFBQTtBQUFBLE1BRWpCO0FBRU8sTUFBTSwrQkFBK0IsQ0FDMUMsUUFDQSxzQkFDQSxhQUNBLHFCQUNBLGlCQUFpQixPQUNqQiwrQkFDZ0I7QUFDaEIsY0FBTSxTQUFTLE9BQU8sQ0FBQyxFQUFFO0FBQ3pCLGNBQU0sU0FBUyxPQUFPLENBQUMsRUFBRTtBQUV6QixjQUFNLElBQUksT0FBTyxPQUFPLFNBQVMsQ0FBQztBQUNsQyxjQUFNLElBQUksT0FBTyxPQUFPLFNBQVMsQ0FBQztBQUNsQyxjQUFNLElBQUksT0FBTyxPQUFPLFNBQVMsQ0FBQztBQUNsQyxjQUFNLGFBQWEsaUJBQWlCLENBQUM7QUFDckMsY0FBTSxjQUFjLGlCQUFpQixDQUFDO0FBQ3RDLGNBQU0sZUFBZSxpQkFBaUIsQ0FBQztBQUN2QyxjQUFNLGFBQWEsVUFBVSxLQUFLLFdBQVcsSUFBSSxhQUFhO0FBQzlELGNBQU0sVUFBVSxPQUFPLFNBQVM7QUFDaEMsY0FBTSxZQUFZLHNCQUFzQixvQkFBb0IsTUFBTSxHQUFHLEVBQUUsSUFBSSxZQUFZLE1BQU0sR0FBRyxFQUFFO0FBQ2xHLGNBQU0sWUFBWSxVQUFVLEtBQUssU0FBUztBQUMxQyxjQUFNLHNCQUFzQixDQUFDLFdBQVcsR0FBRyxDQUFDO0FBRTVDLGNBQU0sa0JBQW9DO0FBQUEsVUFDeEMsRUFBRSx1QkFBdUIsTUFBTSxXQUFXO0FBQUEsVUFDMUMsRUFBRSx1QkFBdUIsTUFBTSxFQUFFO0FBQUEsVUFDakMsRUFBRSx1QkFBdUIsTUFBTSxFQUFFO0FBQUEsVUFDakMsRUFBRSx1QkFBdUIsTUFBTSxFQUFFO0FBQUEsUUFDbkM7QUFDQSxxQ0FBNkIsc0JBQXNCLGVBQWU7QUFDbEUsd0JBQWdCLEtBQUssR0FBRywyQkFBMkIsV0FBVyxRQUFRLE1BQU0sQ0FBQztBQUM3RSxZQUFJLFNBQVM7QUFDWCwwQkFBZ0IsS0FBSyxHQUFHLDJCQUEyQixPQUFPLENBQUMsRUFBRSxJQUFJLENBQUM7QUFBQSxRQUNwRTtBQUNBLHdCQUFnQixLQUFLLEdBQUcsMkJBQTJCLG1CQUFtQixDQUFDO0FBRXZFLGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQ3RELGdCQUFNLFlBQVksaUJBQWlCLGNBQWMsT0FBTyxDQUFDLEVBQUUsVUFBVSxVQUFVLE1BQU07QUFDckYsZ0JBQU0sSUFBSSxjQUFjLEtBQUssT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLFFBQVEsV0FBVztBQUMzRSxnQkFBTSxJQUFJLGNBQWMsS0FBSyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sUUFBUSxVQUFVO0FBQzFFLGdCQUFNLFNBQVMsZUFBZSxVQUFVLE9BQU8sQ0FBQyxFQUFFLFVBQVUsb0JBQW9CLFFBQVEsVUFBVTtBQUNsRyxnQkFBTSxXQUFXLDRCQUE0QixPQUFPLEtBQUssTUFBTTtBQUMvRCxnQkFBTSxrQkFBa0IscUJBQXFCLHNCQUFzQixPQUFPLEtBQUssT0FBTyxRQUFRO0FBQzlGLGdCQUFNLGlCQUFpQixDQUFDLEdBQUcsQ0FBQztBQUM1QixjQUFJLGNBQWM7QUFDbEIsY0FBSSxTQUFTO0FBQ1gsa0JBQU0saUJBQWlCLGlCQUFpQixhQUFhO0FBQ3JELDJCQUFlLEtBQUssY0FBYyxRQUFRLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxDQUFDLEVBQUUsS0FBSyxRQUFRLGNBQWMsQ0FBQztBQUNwRywwQkFBYyxHQUNaLGlCQUFpQix1QkFBdUIsY0FBYyxPQUFPLFlBQVksT0FBTyxLQUFLLEtBQUssa0JBQzVGO0FBQUEsVUFDRjtBQUVBLGdCQUFNLFdBQThCO0FBQUEsWUFDbEMsRUFBRSxNQUFNLGVBQWUsTUFBTSxNQUFNO0FBQUEsWUFDbkMsRUFBRSxNQUFNLEtBQUssTUFBTSxNQUFNO0FBQUEsWUFDekIsRUFBRSxNQUFNLEtBQUssTUFBTSxNQUFNO0FBQUEsWUFDekIsRUFBRSxNQUFNLEtBQUssTUFBTSxNQUFNO0FBQUEsVUFDM0I7QUFDQSxtQ0FBeUIsc0JBQXNCLFFBQVE7QUFFdkQsZ0JBQU0sYUFBYSxNQUFjO0FBQy9CLGdCQUFJLFVBQVUsZUFBZSxFQUFFLEtBQUssS0FBSztBQUN6QyxxQkFBUyxJQUFJLEdBQUcsSUFBSSxhQUFhLEtBQUs7QUFDcEMseUJBQVc7QUFBQSwwQkFDTyxDQUFDLHlCQUF5QixDQUFDLDJCQUEyQixVQUFVO0FBQUEsWUFDcEY7QUFDQSxxQkFBUyxJQUFJLEdBQUcsSUFBSSxjQUFjLEtBQUs7QUFDckMseUJBQVcsaUNBQWlDLENBQUMseUJBQXlCLFdBQVc7QUFFakYsdUJBQVMsSUFBSSxHQUFHLElBQUksYUFBYSxLQUFLO0FBQ3BDLDJCQUFXO0FBQUEscUJBQ0EsQ0FBQyxXQUFXLEVBQUUsS0FBSyxLQUFLLFVBQVUsZ0JBQWdCLElBQUksS0FBSyxJQUFJLENBQUMsR0FBRyxZQUFZLENBQUMsWUFBWSxDQUFDO0FBQUE7QUFBQSxjQUMxRztBQUFBLFlBQ0Y7QUFDQSxtQkFBTztBQUFBLFVBQ1Q7QUFFQSxpQkFBTztBQUFBLElBQ1AsYUFDQyxpQkFBaUIsUUFBUSxFQUN6QiwwQkFBMEIsU0FBUyxFQUNuQyxpQkFBaUIsR0FBRyxnQkFBZ0IsTUFBTSxDQUFDO0FBQUEsSUFDNUMsYUFBYSxVQUFVLENBQUM7QUFBQSxNQUN0QixhQUFhLHNDQUFzQyxzQkFBc0IsQ0FBQztBQUFBLDRDQUNwQyxVQUFVLFFBQVEsVUFBVTtBQUFBLDhDQUMxQixVQUFVO0FBQUEsaUNBQ3ZCLFlBQVk7QUFBQSxxQ0FDUixZQUFZO0FBQUE7QUFBQTtBQUFBLE1BRzNDLFlBQVksV0FBVyxJQUFJLEtBQUssdUJBQXVCLFVBQVUsZ0JBQWdCLE9BQU8sQ0FBQyxHQUFHO0FBQUE7QUFBQSxxQkFFN0UsRUFBRSxLQUFLLE9BQU87QUFBQSxNQUM3Qiw2Q0FBNkMsYUFBYSxHQUFHLEVBQUUsT0FBTyxHQUFHLFVBQVUsTUFBTSxlQUFlLENBQUM7QUFBQSxNQUN6RyxFQUFFLFdBQVcsYUFBYSxFQUFFLE9BQU8sR0FBRyxDQUFDLENBQUM7QUFBQSxNQUN4QyxFQUFFLFdBQVcsYUFBYSxFQUFFLE9BQU8sR0FBRyxDQUFDLENBQUM7QUFBQSxxQkFDekIsRUFBRSxnQkFBZ0IsV0FBVyxDQUFDO0FBQUE7QUFBQSxxQkFFOUIsRUFBRSxLQUFLLE9BQU87QUFBQSxNQUM3Qiw2Q0FBNkMsYUFBYSxHQUFHLEVBQUUsT0FBTyxHQUFHLFVBQVUsTUFBTSxlQUFlLENBQUM7QUFBQSxNQUN6RyxFQUFFLFdBQVcsYUFBYSxFQUFFLE9BQU8sR0FBRyxDQUFDLENBQUM7QUFBQSxNQUN4QyxFQUFFLFdBQVcsYUFBYSxFQUFFLE9BQU8sR0FBRyxDQUFDLENBQUM7QUFBQSxxQkFDekIsRUFBRSxnQkFBZ0IsV0FBVyxDQUFDO0FBQUEsd0JBQzNCLE9BQU8sS0FBSyxLQUFLLEtBQUssWUFBWTtBQUFBLG9EQUNOLFdBQVc7QUFBQSxRQUN2RCxXQUFXLENBQUM7QUFBQTtBQUFBLDJCQUVPLFlBQVk7QUFBQTtBQUFBLFFBRS9CLFdBQVc7QUFBQSxRQUNYLGVBQWU7QUFBQSwwQkFDRyxPQUFPLEtBQUssT0FBTztBQUFBLHFCQUN4QixPQUFPLGdCQUFnQixhQUFhLENBQUM7QUFBQSxRQUNsRCxPQUFPLFlBQVksWUFBWSxVQUFVLElBQUksT0FBTyxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFJM0Q7QUFDQSxlQUFPO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixhQUFhO0FBQUEsWUFDWCxNQUFNLEdBQUcscUJBQXFCLFVBQVUsSUFBSSxVQUFVLElBQUksV0FBVyxJQUFJLFlBQVksSUFBSSxjQUFjO0FBQUEsWUFDdkcsbUJBQW1CLFVBQVUsQ0FBQyxRQUFRLFFBQVEsTUFBTSxJQUFJLENBQUMsUUFBUSxNQUFNO0FBQUEsVUFDekU7QUFBQSxVQUNBLFlBQVksT0FBTztBQUFBLFlBQ2pCLFNBQVM7QUFBQSxjQUNQO0FBQUEsZ0JBQ0UsTUFBTSw2QkFBNkIsMkJBQTJCLFdBQVcsSUFBSTtBQUFBLGdCQUM3RSxVQUFVLE9BQU8sQ0FBQyxFQUFFO0FBQUEsY0FDdEI7QUFBQSxZQUNGO0FBQUEsWUFDQSxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxhQUFhO0FBQUE7QUFBQSxZQUF1QixFQUFFO0FBQUEsWUFDcEU7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBQUE7QUFBQTs7O0FDOUxBLE1BNkNNLDRCQWdCQSx3QkF5Qk8sNEJBa0dQLHdCQWdCQSx5QkFLTyx3QkFxS1AseUJBMkVPO0FBN2JiO0FBQUE7QUFBQTtBQXFCQTtBQUVBO0FBRUE7QUFVQTtBQU1BO0FBRUE7QUFFQSxNQUFNLDZCQUE2QixDQUFDQyxZQUFvQixjQUE4QjtBQUNwRixZQUFJQSxZQUFXO0FBQ2IsaUJBQU87QUFBQTtBQUFBO0FBQUEsd0RBRzZDLFlBQVksbUJBQW1CLEVBQUU7QUFBQTtBQUFBLFFBRXZGLE9BQU87QUFDTCxpQkFBTztBQUFBO0FBQUE7QUFBQSxnREFHcUMsWUFBWSxtQkFBbUIsRUFBRTtBQUFBO0FBQUEsUUFFL0U7QUFBQSxNQUNGO0FBRUEsTUFBTSx5QkFBeUIsQ0FBQyxZQUFxQixxQkFBNkI7QUFDaEYsWUFBSSxZQUFZO0FBQ2QsaUJBQU87QUFBQTtBQUFBO0FBQUE7QUFBQSxVQUlELHFCQUFxQixJQUFJLEtBQUssNkRBQTZEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxZQUt6RixxQkFBcUIsSUFBSSxLQUFLLDJDQUEyQztBQUFBO0FBQUEsUUFFbkYsT0FBTztBQUNMLGlCQUFPO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFlBTUMscUJBQXFCLElBQUksS0FBSyx5Q0FBeUM7QUFBQTtBQUFBLFFBRWpGO0FBQUEsTUFDRjtBQUVPLE1BQU0sNkJBQTZCLENBQ3hDLGVBQ0EsZUFDQSxPQUFPLE9BQ1AsV0FDQSxhQUFhLE9BQ2IsWUFBWSxJQUNaLFNBQVMsT0FDVCxrQkFBa0IsT0FDUDtBQUNYLGNBQU0sYUFBYSxjQUFjLENBQUMsSUFBSSxjQUFjLENBQUM7QUFDckQsY0FBTSxhQUFhLGNBQWMsQ0FBQyxJQUFJLGNBQWMsQ0FBQztBQUNyRCxjQUFNLGFBQWEsYUFBYSxhQUFhO0FBQzdDLGNBQU0sYUFBYSxhQUFhLFlBQVk7QUFDNUMsY0FBTSxtQkFBbUIsYUFBYSxjQUFjLENBQUM7QUFDckQsY0FBTSxnQkFBZ0IsWUFBWSxjQUFjLENBQUM7QUFFakQsWUFDRSxHQUNJLGNBQWMscUJBQXFCLEtBQUssY0FBYyxDQUFDLE1BQU0sS0FDNUQsQ0FBQyxlQUFlLHFCQUFxQixLQUFLLHFCQUFxQixPQUNsRSxhQUFhLGNBQWMsQ0FBQyxNQUFNLEtBQ2xDLFlBQVksY0FBYyxDQUFDLE1BQU0sS0FDakMsY0FBYyxDQUFDLE1BQU0sSUFFdkI7QUFDQSxnQkFBTSxJQUFJLE1BQU0saUJBQWlCLFVBQVUsOEJBQThCLGdCQUFnQix5QkFBeUIsY0FBYyxDQUFDLENBQUM7QUFBQSxvQ0FDbEcsZ0JBQWdCO0FBQUEsZUFDckMsVUFBVSx5Q0FBeUMsY0FBYyxDQUFDLENBQUMsZUFBZSxTQUFTLDBDQUEwQyxjQUFjLENBQUMsQ0FBQyxrQkFBa0IsY0FBYyxDQUFDLENBQUMsYUFBYTtBQUFBLFFBQ2pOO0FBQ0EsZUFBTztBQUFBLHlDQUNnQyxnQkFBZ0IsSUFBSSxJQUFJLE1BQU0sYUFBYSxnQkFBZ0IsTUFBTSxVQUFVO0FBQUEsMkNBQ3pFLElBQUksTUFBTSxhQUFhLGNBQWMsQ0FBQyxDQUFDLE1BQU0sU0FBUztBQUFBO0FBQUEsdUJBRTFFLGNBQWMsQ0FBQyxDQUFDO0FBQUEsdUJBQ2hCLGNBQWMsQ0FBQyxDQUFDO0FBQUEsMkJBQ1osZ0JBQWdCO0FBQUEsb0JBQ3ZCLFNBQVM7QUFBQTtBQUFBLDJCQUVGLGNBQWMsQ0FBQyxDQUFDLEtBQUssY0FBYyxDQUFDLENBQUMsS0FBSyxjQUFjLENBQUMsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGdCQVVyRSxTQUFTLE1BQU0saUJBQWlCO0FBQUEsSUFDNUMsWUFBWSxzQkFBc0IsVUFBVSxnQkFBZ0IsWUFBWSxDQUFDLE1BQU0sRUFBRTtBQUFBLDhDQUN2QyxVQUFVO0FBQUE7QUFBQSxvQkFFcEMsU0FBUyxHQUFHLEtBQUssS0FBSyxrQkFBa0IsU0FBUyxDQUFDLEtBQUssMENBQTBDO0FBQUEsaUJBQ3BHLFNBQVMscUJBQXFCLGVBQWUsS0FBSyxHQUFHO0FBQUE7QUFBQSx3QkFFOUMsSUFBSTtBQUFBO0FBQUE7QUFBQSw4QkFHRSxhQUFhO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFlBTS9CLDJCQUEyQixZQUFZLFNBQVMsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBLDBDQUluQixhQUFhO0FBQUE7QUFBQTtBQUFBLHNGQUkzQyxZQUFZLG1CQUFtQixFQUNqQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFlBVUUscUJBQXFCLElBQUksS0FBSyw0REFBNEQ7QUFBQTtBQUFBLFlBRTFGLHVCQUF1QixZQUFZLGdCQUFnQixDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsTUFVaEU7QUFFQSxNQUFNLHlCQUF5QixDQUFDQSxZQUFvQixjQUE4QjtBQUNoRixZQUFJQSxZQUFXO0FBQ2IsaUJBQU87QUFBQTtBQUFBO0FBQUEseUNBRzhCLFlBQVksbUJBQW1CLEVBQUU7QUFBQTtBQUFBLFFBRXhFLE9BQU87QUFDTCxpQkFBTztBQUFBO0FBQUE7QUFBQSxpQ0FHc0IsWUFBWSxtQkFBbUIsRUFBRTtBQUFBO0FBQUEsUUFFaEU7QUFBQSxNQUNGO0FBRUEsTUFBTSwwQkFBMEIsQ0FBQyxlQUMvQixhQUFhLGtEQUFrRDtBQUkxRCxNQUFNLHlCQUF5QixDQUNwQyxlQUNBLGVBQ0EsT0FBTyxPQUNQLFdBQ0EsYUFBYSxPQUNiLFlBQVksSUFDWixTQUFTLE9BQ1Qsa0JBQWtCLElBQ2xCLDRCQUE0QixVQUNqQjtBQUNYLGNBQU0sYUFBYSxjQUFjLENBQUMsSUFBSSxjQUFjLENBQUM7QUFDckQsY0FBTSxhQUFhLGNBQWMsQ0FBQyxJQUFJLGNBQWMsQ0FBQztBQUNyRCxjQUFNLGFBQWEsYUFBYSxhQUFhO0FBQzdDLGNBQU0sYUFBYSxhQUFhLFlBQVk7QUFFNUMsWUFDRSxFQUFFLGFBQWEsY0FBYyxDQUFDLE1BQU0sS0FBSyxhQUFhLGNBQWMsQ0FBQyxNQUFNLEtBQUssWUFBWSxjQUFjLENBQUMsTUFBTSxJQUNqSDtBQUNBLGdCQUFNLElBQUk7QUFBQSxZQUNSLGNBQWMsVUFBVSx5Q0FBeUMsY0FBYyxDQUFDLENBQUMsZ0JBQWdCLFVBQVUseUNBQXlDLGNBQWMsQ0FBQyxDQUFDLGVBQWUsU0FBUyx5Q0FBeUMsY0FBYyxDQUFDLENBQUM7QUFBQSxVQUN2UDtBQUFBLFFBQ0Y7QUFDQSxjQUFNLGdCQUFnQixhQUFhLGNBQWMsQ0FBQztBQUNsRCxjQUFNLGdCQUFnQixhQUFhLGNBQWMsQ0FBQztBQUNsRCxjQUFNLGdCQUFnQixZQUFZLGNBQWMsQ0FBQztBQUNqRCxjQUFNLGdCQUFnQiw0QkFDbEI7QUFBQTtBQUFBO0FBQUEsZ0RBRzBDLFVBQVU7QUFBQSxnREFDVixVQUFVO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxpREFLVCxVQUFVLDJCQUEyQixjQUFjLENBQUMsQ0FBQztBQUFBLG1EQUNuRCxVQUFVLDJCQUEyQixjQUFjLENBQUMsQ0FBQztBQUFBLFlBQzVGLHVCQUF1QixZQUFZLFNBQVMsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBLGlEQUlSLFNBQVMsMkJBQTJCLGNBQWMsQ0FBQyxDQUFDO0FBQUEsdURBQzlDLFVBQVUsMkJBQTJCLGNBQWMsQ0FBQyxDQUFDO0FBQUE7QUFBQTtBQUFBLHVDQUdyRSxZQUFZLG1CQUFtQixFQUFFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsNEJBTzVDLElBQUk7QUFBQTtBQUFBO0FBQUEsMkRBRzJCLGNBQWMsQ0FBQyxDQUFDO0FBQUE7QUFBQTtBQUFBLDBCQUkvRCxhQUNJLG9DQUFvQyxjQUFjLENBQUMsQ0FBQyxPQUNwRCxpQ0FBaUMsY0FBYyxDQUFDLENBQUMsT0FDdkQ7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSwwREFVZ0QsY0FBYyxDQUFDLENBQUM7QUFBQTtBQUFBLDREQUVkLGNBQWMsQ0FBQyxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFLdEU7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsNENBTXNDLFVBQVU7QUFBQTtBQUFBLGtDQUVwQixhQUFhO0FBQUEsa0NBQ2IsYUFBYTtBQUFBLGtDQUNiLGFBQWE7QUFBQTtBQUFBO0FBQUE7QUFBQSxzQ0FJVCxhQUFhO0FBQUEsd0NBQ1gsYUFBYTtBQUFBO0FBQUE7QUFBQSxRQUc3Qyx1QkFBdUIsWUFBWSxTQUFTLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHNDQUtmLGFBQWE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsOEJBTXJCLFlBQVksbUJBQW1CLEVBQUU7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSx3QkFPdkMsSUFBSTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBT3BCLHdCQUF3QixVQUFVLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQWtCekMsZUFBTztBQUFBLHlDQUNnQyxJQUFJLEtBQUssVUFBVSxNQUFNLFVBQVU7QUFBQSx5Q0FDbkMsSUFBSSxLQUFLLFVBQVUsTUFBTSxTQUFTO0FBQUEseUJBQ2xELGNBQWMsQ0FBQyxDQUFDO0FBQUEseUJBQ2hCLGNBQWMsQ0FBQyxDQUFDO0FBQUEsc0JBQ25CLFNBQVM7QUFBQTtBQUFBLDJCQUVKLGNBQWMsQ0FBQyxDQUFDLEtBQUssY0FBYyxDQUFDLENBQUMsS0FBSyxjQUFjLENBQUMsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUluRSxTQUFTLE1BQU0saUJBQWlCO0FBQUEsTUFDNUMsWUFBWSxzQkFBc0IsVUFBVSxnQkFBZ0IsWUFBWSxDQUFDLE1BQU0sRUFBRTtBQUFBLHNCQUVqRixTQUFTLEdBQUcsS0FBSyxLQUFLLGtCQUFrQixTQUFTLENBQUMsS0FBSywwQ0FDekQ7QUFBQSxtQkFDZSxTQUFTLHFCQUFxQixlQUFlLEtBQUssR0FBRztBQUFBO0FBQUEsNEJBRTVDLElBQUk7QUFBQSxNQUMxQixhQUFhO0FBQUE7QUFBQTtBQUFBLE1BR25CO0FBRUEsTUFBTSwwQkFBMEIsQ0FDOUIsV0FDQSxTQUNBLGlCQUNBLFdBQ0EsaUJBQWlCLFVBQ047QUFDWCxjQUFNLENBQUMsZUFBZSxXQUFXLFdBQVdDLGVBQWMsSUFBSTtBQUM5RCxjQUFNLFdBQVcsNEJBQTRCLFVBQVUsQ0FBQyxFQUFFLEtBQUssTUFBTTtBQUVyRSxjQUFNLFNBQVM7QUFBQSxrRUFDaUQsY0FBYyxLQUFLLE9BQU8sUUFBUTtBQUFBLFVBQzlGO0FBQUEsVUFDQTtBQUFBLFFBQ0YsQ0FBQztBQUFBLG9CQUNlLFlBQVksV0FBVyxRQUFRLENBQUM7QUFBQSwwQkFDMUIsU0FBUztBQUFBO0FBQUE7QUFBQSx3QkFHWCxVQUFVLEtBQUssT0FBTztBQUFBLFVBQ3BDO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBLFVBQVUsT0FBTztBQUFBLFVBQ2pCLGNBQWM7QUFBQSxVQUNkO0FBQUEsUUFDRixDQUFDO0FBQUEsVUFDQyxVQUFVLFdBQVcsWUFBWSxVQUFVLE9BQU8sR0FBRyxVQUFVLENBQUM7QUFBQSxVQUNoRSxVQUFVLFdBQVcsWUFBWSxVQUFVLE9BQU8sR0FBRyxZQUFZLENBQUM7QUFBQSxrQkFDMUQsVUFBVSxhQUFhLFVBQVUsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0VBS2MsY0FBYyxLQUFLLE9BQU8sUUFBUTtBQUFBLFVBQzlGO0FBQUEsVUFDQTtBQUFBLFFBQ0YsQ0FBQztBQUFBLG9CQUNlLFlBQVksV0FBVyxRQUFRLENBQUM7QUFBQSwwQkFDMUIsU0FBUztBQUFBO0FBQUE7QUFBQSx3QkFHWCxVQUFVLEtBQUssT0FBTztBQUFBLFVBQ3BDO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBLFVBQVUsT0FBTztBQUFBLFVBQ2pCLGNBQWM7QUFBQSxVQUNkO0FBQUEsUUFDRixDQUFDO0FBQUEsVUFDQyxVQUFVLFdBQVcsWUFBWSxVQUFVLE9BQU8sR0FBRyxVQUFVLENBQUM7QUFBQSxVQUNoRSxVQUFVLFdBQVcsWUFBWSxVQUFVLE9BQU8sR0FBRyxZQUFZLENBQUM7QUFBQSxrQkFDMUQsVUFBVSxhQUFhLFVBQVUsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsNkRBS1MsWUFBWSxXQUFXLFFBQVEsQ0FBQztBQUFBLDBCQUNuRSxTQUFTO0FBQUE7QUFBQTtBQUFBO0FBQUEsVUFLekIsVUFDSSxtQkFBbUIsaUJBQWlCLGdCQUFnQixHQUFHLFlBQVksV0FBVyxRQUFRLENBQUMsYUFBYSxNQUNwRyxFQUNOO0FBQUEsVUFDRSxlQUFlO0FBQUEsVUFDZkEsZ0JBQWUsYUFBYSxxQkFBcUIsT0FBTyxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBSWpFLGVBQU87QUFBQSxNQUNUO0FBRU8sTUFBTSwwQkFBMEIsQ0FDckMsUUFDQSxzQkFDQSxhQUNBLHFCQUNBLGlCQUFpQixPQUNqQiwrQkFDZ0I7QUFDaEIsY0FBTSxTQUFTLE9BQU8sQ0FBQyxFQUFFO0FBQ3pCLGNBQU0sU0FBUyxPQUFPLENBQUMsRUFBRTtBQUN6QixjQUFNLGFBQWEsT0FBTyxNQUFNLEdBQUcsRUFBRTtBQUNyQyxjQUFNLGFBQWEsT0FBTyxNQUFNLEdBQUcsRUFBRTtBQUNyQyxjQUFNLFlBQVksc0JBQXNCLG9CQUFvQixNQUFNLEdBQUcsRUFBRSxJQUFJLFlBQVksTUFBTSxHQUFHLEVBQUU7QUFDbEcsY0FBTSxZQUFZLFVBQVUsS0FBSyxTQUFTO0FBQzFDLGNBQU0sWUFBWSxPQUFPLE9BQU8sU0FBUyxDQUFDO0FBQzFDLGNBQU0sV0FBVyxPQUFPLE9BQU8sU0FBUyxDQUFDO0FBQ3pDLGNBQU0sWUFBWSxPQUFPLE9BQU8sU0FBUyxDQUFDO0FBQzFDLGNBQU0sU0FBUyxXQUFXLE1BQU0sS0FBSyxZQUFZLE1BQU07QUFHdkQsY0FBTSxvQkFBb0IsYUFBYSxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDO0FBQy9ELGNBQU0sZ0JBQTBDLENBQUMsR0FBRyxHQUFHLENBQUM7QUFDeEQsY0FBTSxXQUFXO0FBQUEsVUFDZixLQUFLLEtBQUssWUFBWSxjQUFjLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxDQUFDO0FBQUEsVUFDN0QsS0FBSyxLQUFLLFlBQVksY0FBYyxDQUFDLElBQUksa0JBQWtCLENBQUMsQ0FBQztBQUFBLFVBQzdELEtBQUssS0FBSyxZQUFZLGNBQWMsQ0FBQyxJQUFJLGtCQUFrQixDQUFDLENBQUM7QUFBQSxRQUMvRDtBQUVBLGNBQU0sYUFBYSxTQUFTLElBQUk7QUFDaEMsY0FBTSxhQUFhLENBQUMsR0FBRyxZQUFZLFdBQVcsV0FBVyxVQUFVO0FBQ25FLGNBQU0sUUFBUSxXQUFXO0FBQ3pCLGNBQU0sYUFBYSxDQUFDLEdBQUcsWUFBWSxVQUFVLFlBQVksVUFBVTtBQUNuRSxjQUFNLFFBQVEsV0FBVztBQUN6QixjQUFNLGtCQUFrQixDQUFDLFdBQVcsV0FBVyxZQUFZLFVBQVU7QUFDckUsY0FBTSxrQkFBb0M7QUFBQSxVQUN4QyxFQUFFLHFCQUFzQixNQUFNLFVBQVU7QUFBQSxVQUN4QyxFQUFFLHFCQUFzQixNQUFNLFVBQVU7QUFBQSxVQUN4QyxFQUFFLHFCQUFzQixNQUFNLFNBQVM7QUFBQSxRQUN6QztBQUNBLHFDQUE2QixzQkFBc0IsZUFBZTtBQUNsRSx3QkFBZ0IsS0FBSyxHQUFHLDJCQUEyQixXQUFXLFlBQVksVUFBVSxDQUFDO0FBQ3JGLGNBQU0sb0JBQXdELENBQUMsUUFBUSxNQUFNO0FBRTdFLGNBQU0sVUFBVSxPQUFPLFNBQVM7QUFDaEMsWUFBSSxTQUFTO0FBQ1gsMEJBQWdCLEtBQUssR0FBRywyQkFBMkIsT0FBTyxDQUFDLEVBQUUsSUFBSSxDQUFDO0FBQ2xFLDRCQUFrQixLQUFLLE1BQU07QUFBQSxRQUMvQjtBQUNBLHdCQUFnQixLQUFLLEdBQUcsMkJBQTJCLGVBQWUsQ0FBQztBQUVuRSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxnQkFBTSxZQUFZLFVBQVU7QUFDNUIsZ0JBQU0sWUFBWSxpQkFBaUIsYUFBYSxPQUFPLENBQUMsRUFBRSxVQUFVLFdBQVcsQ0FBQztBQUNoRixnQkFBTSxXQUFXLDRCQUE0QixPQUFPLENBQUMsRUFBRSxRQUFRO0FBRS9ELGdCQUFNLElBQUksY0FBYyxLQUFLLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxVQUFVO0FBQ2xFLGdCQUFNLElBQUksY0FBYyxLQUFLLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxVQUFVO0FBQ2xFLGdCQUFNLFNBQVMsZUFBZSxVQUFVLE9BQU8sQ0FBQyxFQUFFLFVBQVUsZ0JBQWdCLFFBQVEsVUFBVTtBQUM5RixnQkFBTSxpQkFBaUIsQ0FBQyxHQUFHLENBQUM7QUFDNUIsY0FBSSxTQUFTO0FBQ1gsa0JBQU0saUJBQWlCLGlCQUFpQixhQUFhO0FBQ3JELDJCQUFlLEtBQUssY0FBYyxRQUFRLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxDQUFDLEVBQUUsS0FBSyxRQUFRLGNBQWMsQ0FBQztBQUFBLFVBQ3RHO0FBQ0EsZ0JBQU0sV0FBOEI7QUFBQSxZQUNsQyxFQUFFLE1BQU0sZUFBZSxNQUFNLE1BQU07QUFBQSxZQUNuQyxFQUFFLE1BQU0sZUFBZSxNQUFNLE1BQU07QUFBQSxZQUNuQyxFQUFFLE1BQU0sYUFBYSxNQUFNLE1BQU07QUFBQSxVQUNuQztBQUNBLG1DQUF5QixzQkFBc0IsUUFBUTtBQUN2RCxnQkFBTSxXQUFXLDRCQUE0QixPQUFPLEtBQUssTUFBTTtBQUMvRCxnQkFBTSxrQkFBa0IscUJBQXFCLHNCQUFzQixPQUFPLEtBQUssT0FBTyxRQUFRO0FBQzlGLGdCQUFNLG1CQUFtQjtBQUFBLFlBQ3ZCO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBLENBQUMsV0FBVyxHQUFHLEdBQUcsTUFBTTtBQUFBLFlBQ3hCO0FBQUEsVUFDRjtBQUNBLGlCQUFPO0FBQUEsSUFDUCxhQUNDLGlCQUFpQixRQUFRLEVBQ3pCLDBCQUEwQixTQUFTLEVBQ25DLGlCQUFpQixHQUFHLGdCQUFnQixNQUFNLENBQUM7QUFBQSxJQUM1QyxnQkFBZ0I7QUFBQSxJQUVoQixTQUNJLDJCQUEyQixtQkFBbUIsZUFBZSxVQUFVLFNBQVMsSUFDaEYsdUJBQXVCLG1CQUFtQixlQUFlLFVBQVUsU0FBUyxDQUNsRjtBQUFBO0FBQUEsUUFFQTtBQUNBLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWE7QUFBQSxZQUNYLE1BQU0sR0FBRyxpQkFBaUIsSUFBSSxxQkFBcUIsVUFBVSxJQUFJLE1BQU0sSUFBSSxjQUFjO0FBQUEsWUFDekY7QUFBQSxVQUNGO0FBQUEsVUFDQSxZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTO0FBQUEsY0FDUDtBQUFBLGdCQUNFLE1BQU0sNkJBQTZCLDJCQUEyQixXQUFXLElBQUk7QUFBQSxnQkFDN0UsVUFBVSxPQUFPLENBQUMsRUFBRTtBQUFBLGNBQ3RCO0FBQUEsWUFDRjtBQUFBLFlBQ0EsZUFBZSxFQUFFLEdBQUcsU0FBUyxDQUFDLEdBQUcsR0FBRyxTQUFTLENBQUMsR0FBRyxHQUFHLFNBQVMsQ0FBQyxFQUFFO0FBQUEsWUFDaEU7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBQUE7QUFBQTs7O0FDMWlCQSxNQXdDTSxxQkFxSk87QUE3TGI7QUFBQTtBQUFBO0FBcUJBO0FBQ0E7QUFHQTtBQVNBO0FBRUE7QUFDQTtBQUNBO0FBRUEsTUFBTSxzQkFBc0IsQ0FDMUIsZ0JBQ0EsV0FDQSxXQUNBLFVBQ0EsVUFBVSxPQUNWLFlBQ0Esb0JBQW9CLEdBQ3BCLG9CQUFvQixHQUNwQixtQkFBbUIsR0FDbkIsV0FBVyxVQUNBO0FBQ1gsY0FBTSxjQUFjLENBQUNDLHNCQUE2QjtBQUNoRCxrQkFBUUEsbUJBQWtCO0FBQUEsWUFDeEIsS0FBSztBQUNILHFCQUFPO0FBQUEsWUFDVCxLQUFLO0FBQ0gscUJBQU8sa0JBQWtCLFFBQVE7QUFBQSxZQUNuQyxLQUFLO0FBQ0gscUJBQU87QUFBQSxZQUNUO0FBQ0Usb0JBQU0sSUFBSSxNQUFNLG9CQUFvQkEsaUJBQWdCLG9CQUFvQjtBQUFBLFVBQzVFO0FBQUEsUUFDRjtBQUNBLGNBQU0sY0FBYyxDQUFDQSxzQkFBNkI7QUFDaEQsa0JBQVFBLG1CQUFrQjtBQUFBLFlBQ3hCLEtBQUs7QUFDSCxxQkFBTztBQUFBLFlBQ1QsS0FBSztBQUNILHFCQUFPO0FBQUEsWUFDVDtBQUNFLG9CQUFNLElBQUksTUFBTSxvQkFBb0JBLGlCQUFnQixvQkFBb0I7QUFBQSxVQUM1RTtBQUFBLFFBQ0Y7QUFDQSxjQUFNLGdCQUFnQixpQkFDbEI7QUFBQTtBQUFBLFFBR0E7QUFBQTtBQUFBO0FBSUosY0FBTSxrQkFBa0IsaUJBQ3BCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBT0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFRSixjQUFNLFVBQVUsaUJBQWlCLDZCQUE2QjtBQUM5RCxjQUFNLFNBQVMsaUJBQWlCLDZCQUE2QjtBQUM3RCxjQUFNLE1BQU0saUJBQWlCLFFBQVE7QUFDckMsY0FBTSxNQUFNLGlCQUFpQixRQUFRO0FBQ3JDLGNBQU0sZUFBZTtBQUFBO0FBQUEscUJBRUYsaUJBQWlCLGtDQUFrQywrQkFBK0I7QUFBQSxtQkFDcEYsR0FBRztBQUFBLG1CQUNILEdBQUc7QUFBQTtBQUFBLGlCQUVMLEdBQUc7QUFBQSxpQkFDSCxHQUFHO0FBQUE7QUFBQTtBQUFBLGdCQUdKLEdBQUc7QUFBQSxvQkFDQyxZQUFZLG1CQUFtQixRQUFRLENBQUM7QUFBQTtBQUFBO0FBQUEsOEJBRzlCLE9BQU8sMkJBQTJCLE1BQU07QUFBQSxRQUM5RCxhQUFhO0FBQUE7QUFBQSxRQUViLFlBQVksaUJBQWlCLENBQUM7QUFBQTtBQUFBO0FBSXBDLGNBQU0sVUFBVSxpQkFDWixhQUFhLFdBQ1g7QUFBQSx3QkFDZ0IsaUJBQWlCO0FBQUEsTUFDbkMsWUFBWSxLQUNWO0FBQUEsd0JBQ2dCLGlCQUFpQjtBQUFBO0FBQUEsUUFFakMsWUFBWTtBQUFBO0FBQUEsYUFFUCxZQUFZLG1CQUFtQixRQUFRLENBQUMsV0FDL0MsWUFBWSxZQUNWO0FBQUEsd0JBQ2dCLGlCQUFpQjtBQUFBLE1BQ25DLFlBQVksS0FDVjtBQUFBLHdCQUNnQixpQkFBaUI7QUFBQTtBQUFBLFFBRWpDLFlBQVk7QUFBQTtBQUFBLGFBRVAsWUFBWSxtQkFBbUIsUUFBUSxDQUFDO0FBRW5ELGNBQU0sVUFBVSxpQkFDWixZQUFZLFlBQ1YsWUFBWSxpQkFBaUIsSUFDN0I7QUFBQSx3QkFDZ0IsaUJBQWlCO0FBQUE7QUFBQSxRQUVqQyxZQUFZLGlCQUFpQixDQUFDO0FBQUE7QUFBQSxhQUV6QixZQUFZLG1CQUFtQixRQUFRLENBQUMsV0FDL0M7QUFBQSx3QkFDa0IsaUJBQWlCO0FBQUE7QUFBQSxRQUVqQyxZQUFZLGlCQUFpQixDQUFDO0FBQUE7QUFBQSxhQUV6QixZQUFZLG1CQUFtQixRQUFRLENBQUM7QUFFbkQsY0FBTSxVQUFVLFlBQVksa0JBQWtCLFFBQVE7QUFDdEQsY0FBTSxRQUFRLGlCQUFpQixZQUFZLG1CQUFtQixRQUFRLElBQUksWUFBWSxtQkFBbUIsUUFBUTtBQUNqSCxjQUFNLFFBQVEsaUJBQWlCLFlBQVksbUJBQW1CLFFBQVEsSUFBSSxZQUFZLG1CQUFtQixRQUFRO0FBQ2pILGNBQU0sa0JBQWtCLHFCQUFxQixZQUFZLFNBQVMsUUFBUTtBQUMxRSxjQUFNLFdBQVc7QUFBQSx5REFDc0MsS0FBSztBQUFBLFFBQ3RELGlCQUFpQixVQUFVLE9BQU87QUFBQTtBQUFBO0FBQUEseURBR2UsS0FBSztBQUFBLFFBQ3RELGlCQUFpQixVQUFVLE9BQU87QUFBQTtBQUFBO0FBQUEsZ0VBR3NCLE9BQU87QUFBQSwwQkFDN0MsZ0JBQWdCO0FBQUE7QUFBQTtBQUFBO0FBQUEsdUJBSW5CLGlCQUFpQixrQ0FBa0MsK0JBQStCO0FBQUEsUUFDakcsZUFBZTtBQUFBLFFBQ2YsWUFBWSxPQUFPLENBQUM7QUFBQSxRQUNwQixlQUFlO0FBQUE7QUFBQTtBQUFBO0FBSXJCLGVBQU87QUFBQSxNQUNUO0FBRU8sTUFBTSxnQ0FBZ0MsQ0FDM0MsUUFDQSxZQUNBLGFBQ0EsV0FDQSxXQUNBLFVBQ0EsU0FDQSwyQkFDQSwrQkFDZ0I7QUFDaEIsY0FBTSxpQkFBaUIsV0FBVyxXQUFXO0FBQzdDLGNBQU0sYUFBYSxpQkFBaUIsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLElBQUksT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDO0FBQ3hFLGNBQU0sWUFBWSxZQUFZLENBQUM7QUFDL0IsY0FBTSxXQUFXLGlCQUFpQixZQUFZLENBQUMsSUFBSSxZQUFZLENBQUM7QUFDaEUsY0FBTSxZQUFZLGlCQUFpQixZQUFZLENBQUMsSUFBSSxZQUFZLENBQUM7QUFDakUsY0FBTSxjQUFjLGlCQUFpQixZQUFZLENBQUMsSUFBSSxZQUFZLENBQUM7QUFFbkUsY0FBTSxTQUFTLG1CQUFtQixhQUFhLE1BQU0sS0FBSyxhQUFhLE1BQU0sTUFBTSxjQUFjLE1BQU07QUFHdkcsY0FBTSxZQUFZLGlCQUFpQixjQUFjLFdBQVc7QUFDNUQsY0FBTSxZQUFZLGlCQUFpQixXQUFXLFlBQVk7QUFDMUQsY0FBTSxnQkFBMEMsQ0FBQyxHQUFHLEdBQUcsQ0FBQztBQUN4RCxjQUFNLG9CQUFvQixhQUFhLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUM7QUFDL0QsY0FBTSxXQUFXO0FBQUEsVUFDZixLQUFLLEtBQUssWUFBWSxjQUFjLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxDQUFDO0FBQUEsVUFDN0QsS0FBSyxLQUFLLFlBQVksY0FBYyxDQUFDLElBQUksa0JBQWtCLENBQUMsQ0FBQztBQUFBLFVBQzdELEtBQUssS0FBSyxZQUFZLGNBQWMsQ0FBQyxJQUFJLGtCQUFrQixDQUFDLENBQUM7QUFBQSxRQUMvRDtBQUVBLGtCQUFVLFdBQVcsTUFBTSxpQ0FBaUMsUUFBUSxFQUFFO0FBRXRFLGNBQU0sbUJBQW1CLFNBQVUsa0JBQWtCLGFBQWEsTUFBTSxJQUFJLElBQUksSUFBSztBQUNyRixjQUFNLGFBQWEsY0FBYyxDQUFDLElBQUksa0JBQWtCLENBQUM7QUFDekQsY0FBTSxhQUFhLGNBQWMsQ0FBQyxJQUFJLGtCQUFrQixDQUFDO0FBQ3pELGNBQU0sWUFBWSxLQUFLLElBQUksY0FBYyxDQUFDLElBQUksa0JBQWtCLGNBQWMsQ0FBQyxDQUFDO0FBQ2hGLGNBQU0sWUFBWSxZQUFZLGVBQWU7QUFDN0MsY0FBTSxZQUFZLFlBQVksZUFBZTtBQUM3QyxjQUFNLFdBQVcsV0FBVyxjQUFjO0FBQzFDLGNBQU0sZUFBZSxTQUFTLENBQUMsa0JBQWtCLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUM7QUFFakUsY0FBTSxrQkFBb0M7QUFBQSxVQUN4QyxFQUFFLHFCQUFzQixNQUFNLFVBQVU7QUFBQSxVQUN4QyxFQUFFLHFCQUFzQixNQUFNLFVBQVU7QUFBQSxVQUN4QyxFQUFFLHFCQUFzQixNQUFNLFNBQVM7QUFBQSxVQUN2QyxFQUFFLHFCQUFzQixNQUFNLENBQUMsV0FBVyxLQUFLLENBQUMsR0FBRyxXQUFXLEtBQUssQ0FBQyxDQUFDLEVBQUU7QUFBQSxVQUN2RSxFQUFFLHFCQUFzQixNQUFNLFdBQVcsUUFBUTtBQUFBLFVBQ2pELEVBQUUscUJBQXNCLE1BQU0sV0FBVyxVQUFVO0FBQUEsUUFDckQ7QUFDQSxxQ0FBNkIsWUFBWSxlQUFlO0FBQ3hELHdCQUFnQixLQUFLLEdBQUcsMkJBQTJCLE9BQU8sQ0FBQyxFQUFFLE1BQU0sT0FBTyxDQUFDLEVBQUUsSUFBSSxDQUFDO0FBQ2xGLGNBQU0sb0JBQXdELENBQUMsUUFBUSxNQUFNO0FBQzdFLFlBQUksU0FBUztBQUNYLDBCQUFnQixLQUFLLEdBQUcsMkJBQTJCLE9BQU8sQ0FBQyxFQUFFLElBQUksQ0FBQztBQUNsRSw0QkFBa0IsS0FBSyxNQUFNO0FBQUEsUUFDL0I7QUFDQSx3QkFBZ0IsS0FBSyxHQUFHLDJCQUEyQixXQUFXLENBQUM7QUFFL0QsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFDdEQsZ0JBQU0sV0FBOEI7QUFBQSxZQUNsQyxFQUFFLE1BQU0sZUFBZSxNQUFNLE1BQU07QUFBQSxZQUNuQyxFQUFFLE1BQU0sZUFBZSxNQUFNLE1BQU07QUFBQSxZQUNuQyxFQUFFLE1BQU0sYUFBYSxNQUFNLE1BQU07QUFBQSxZQUNqQyxFQUFFLE1BQU0sT0FBTyxNQUFNLE9BQU8sUUFBUSxFQUFFO0FBQUEsWUFDdEMsRUFBRSxNQUFNLFVBQVUsTUFBTSxPQUFPLFFBQVEsRUFBRTtBQUFBLFlBQ3pDLEVBQUUsTUFBTSxZQUFZLE1BQU0sT0FBTyxRQUFRLEVBQUU7QUFBQSxVQUM3QztBQUNBLG1DQUF5QixZQUFZLFFBQVE7QUFHN0MsZ0JBQU0sYUFBYSxTQUFTLElBQUk7QUFDaEMsZ0JBQU0sSUFBSSw0QkFBNEIsT0FBTyxDQUFDLEVBQUUsUUFBUTtBQUN4RCxjQUFJLG1CQUFtQjtBQUFBLHFEQUMwQixTQUFTLFFBQVEsQ0FBQyxNQUFNLENBQUM7QUFBQSw4QkFDaEQsU0FBUyxRQUFRLENBQUMsTUFBTSxDQUFDO0FBQUE7QUFBQSw2RUFFc0IsU0FBUyxRQUFRLENBQUMsTUFBTSxDQUFDO0FBQUE7QUFBQSxxQ0FFakUsU0FBUyxRQUFRLEVBQUU7QUFBQTtBQUVwRCxnQkFBTSxJQUFJO0FBQUEsWUFDUjtBQUFBLFlBQ0EsT0FBTyxDQUFDLEVBQUU7QUFBQSxZQUNWLE9BQU8sQ0FBQyxFQUFFLEtBQUs7QUFBQSxZQUNmLHFCQUFxQixJQUFJLElBQUk7QUFBQSxVQUMvQjtBQUNBLGdCQUFNLElBQUksY0FBYyxLQUFLLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxDQUFDLEVBQUUsS0FBSyxRQUFRLFVBQVU7QUFDbEYsZ0JBQU0saUJBQWlCLENBQUMsR0FBRyxDQUFDO0FBQzVCLGdCQUFNLFNBQVMsZUFBZSxVQUFVLE9BQU8sQ0FBQyxFQUFFLFVBQVUsWUFBWSxRQUFRLFVBQVU7QUFDMUYsY0FBSSxTQUFTO0FBQ1gsa0JBQU0sT0FBTyxjQUFjLFFBQVEsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLFFBQVEsVUFBVTtBQUN4RiwyQkFBZSxLQUFLLElBQUk7QUFDeEIsZ0NBQW9CO0FBQUEsMERBQ2dDLFNBQVMsUUFBUSxDQUFDLE1BQU0sQ0FBQztBQUFBLCtCQUNwRCxpQkFBaUIsTUFBTSxHQUFHLEdBQUcsU0FBUyxRQUFRLEVBQUU7QUFBQTtBQUFBLFVBRTNFO0FBRUEsaUJBQU87QUFBQSxVQUNELGNBQWMseUJBQXlCLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQSxVQUl4QyxhQUFhLGlCQUFpQixRQUFRLEVBQUUsaUJBQWlCLEdBQUcsZ0JBQWdCLE1BQU0sQ0FBQztBQUFBLFVBQ25GLGdCQUFnQjtBQUFBLFVBQ2hCO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQSxhQUFhLENBQUM7QUFBQSxZQUNkLGFBQWEsQ0FBQztBQUFBLFlBQ2QsYUFBYSxDQUFDO0FBQUEsWUFDZDtBQUFBLFVBQ0YsQ0FBQztBQUFBLFVBRUMsU0FDSSwyQkFBMkIsbUJBQW1CLGVBQWUsR0FBRyxRQUFXLENBQUMsZ0JBQWdCLFNBQVMsSUFDckc7QUFBQSxZQUNFO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQSxDQUFDO0FBQUEsWUFDRDtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFVBQ0YsQ0FDTjtBQUFBLFFBQ047QUFDQSxlQUFPO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixhQUFhO0FBQUEsWUFDWCxNQUFNLEdBQUcsV0FBVyxRQUFRLElBQUksZ0JBQWdCLElBQUksTUFBTSxJQUFJLFNBQVMsSUFBSSxTQUFTLElBQUksUUFBUSxJQUFJLFVBQVUsSUFBSSxVQUFVLElBQUksU0FBUztBQUFBLFlBQ3pJO0FBQUEsVUFDRjtBQUFBLFVBQ0EsWUFBWSxPQUFPO0FBQUEsWUFDakIsU0FBUztBQUFBLGNBQ1A7QUFBQSxnQkFDRSxNQUFNLDZCQUE2QiwyQkFBMkIsV0FBVyxJQUFJO0FBQUEsZ0JBQzdFLFVBQVUsT0FBTyxDQUFDLEVBQUU7QUFBQSxjQUN0QjtBQUFBLFlBQ0Y7QUFBQSxZQUNBLGVBQWUsRUFBRSxHQUFHLFNBQVMsQ0FBQyxHQUFHLEdBQUcsU0FBUyxDQUFDLEdBQUcsR0FBRyxTQUFTLENBQUMsRUFBRTtBQUFBLFlBQ2hFO0FBQUEsVUFDRjtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQ3JWQSxNQXdDTSxjQVFBLGtCQUdBLHdCQVFBLG1CQVVBLHNCQW9CQSxvQkE2R08sbUJBNkVBO0FBblJiO0FBQUE7QUFBQTtBQXFCQTtBQUNBO0FBRUE7QUFFQTtBQVVBO0FBRUE7QUFFQSxNQUFNLGVBQWUsQ0FBQyxRQUFrQjtBQUN0QyxZQUFJLFVBQVU7QUFDZCxpQkFBUyxJQUFJLEdBQUcsSUFBSSxJQUFJLFFBQVEsS0FBSztBQUNuQyxxQkFBVyxJQUFJLENBQUM7QUFBQSxRQUNsQjtBQUNBLGVBQU87QUFBQSxNQUNUO0FBRUEsTUFBTSxtQkFBbUIsQ0FBQyxVQUN4QixPQUFPLFVBQVUsV0FBVyxDQUFDLE9BQU8sT0FBTyxLQUFLLElBQUk7QUFFdEQsTUFBTSx5QkFBeUIsQ0FBQyxZQUFvQixhQUE2QjtBQUMvRSxZQUFJLFlBQVksR0FBRztBQUNqQixpQkFBTztBQUFBLFFBQ1Q7QUFFQSxlQUFPLGNBQWMsYUFBYSxNQUFNLFdBQVc7QUFBQSxNQUNyRDtBQUVBLE1BQU0sb0JBQW9CLENBQ3hCLFlBQ0EsV0FDQSxRQUNBLFdBQVcsTUFDQTtBQUNYLGNBQU0scUJBQXFCLHVCQUF1QixXQUFXLFFBQVE7QUFDckUsZUFBTyxLQUFLLE9BQU8sV0FBVyxDQUFDLEtBQUssU0FBUyxLQUFLLFNBQVMsc0JBQXNCLENBQUM7QUFBQSxNQUNwRjtBQUVBLE1BQU0sdUJBQXVCLENBQzNCLFNBQ0EsYUFDQSxhQUNBLFNBQ0EsWUFDcUM7QUFDckMsWUFBSSxXQUFXLE1BQU07QUFFbkIsb0JBQVUsa0JBQWtCLFNBQVMsWUFBWSxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUM7QUFBQSxRQUNqRTtBQUNBLGNBQU0sV0FBNkMsQ0FBQyxHQUFHLEdBQUcsR0FBRyxXQUFXO0FBQ3hFLGlCQUFTLFFBQVEsR0FBRyxRQUFRLEdBQUcsU0FBUztBQUN0QyxjQUFJLFFBQVEsS0FBSyxJQUFJLElBQUksV0FBVyxZQUFZLEtBQUssR0FBRztBQUN0RCxxQkFBUyxLQUFLLElBQUksS0FBSyxPQUFPLFFBQVEsS0FBSyxJQUFJLFlBQVksS0FBSyxJQUFJLElBQUksV0FBVyxRQUFRLEtBQUssSUFBSSxDQUFDO0FBQUEsVUFDdkc7QUFBQSxRQUNGO0FBQ0EsZUFBTztBQUFBLE1BQ1Q7QUFFQSxNQUFNLHFCQUFxQixDQUN6QkMsTUFDQSxTQUNBLFVBQ0EsU0FDQSxhQUNBLGNBQ0EsYUFDQSxhQUNBLGNBQ0EsZ0JBQ2tGO0FBQ2xGLFlBQUk7QUFDSixZQUFJO0FBQ0osWUFBSTtBQUNKLFlBQUk7QUFFSixZQUFJQSxTQUFRLFNBQVM7QUFFbkIsVUFBQUEsT0FBTTtBQUFBLFFBQ1I7QUFFQSxZQUFJLE9BQU9BLFNBQVEsVUFBVTtBQUMzQixvQkFBVSxFQUFFLEtBQUtBLE1BQUssUUFBUUEsTUFBSyxNQUFNQSxNQUFLLE9BQU9BLE1BQUssT0FBT0EsTUFBSyxNQUFNQSxLQUFJO0FBQ2hGLGdCQUFNLFdBQVc7QUFBQSxZQUNmLENBQUMsU0FBUyxVQUFVLFNBQVMsQ0FBQztBQUFBLFlBQzlCLENBQUMsYUFBYSxjQUFjLFdBQVc7QUFBQSxZQUN2QztBQUFBLFlBQ0EsQ0FBQyxhQUFhLGNBQWMsV0FBVztBQUFBLFlBQ3ZDQTtBQUFBLFVBQ0Y7QUFDQSxxQkFBVyxTQUFTLENBQUM7QUFDckIsc0JBQVksU0FBUyxDQUFDO0FBQ3RCLHFCQUFXLFNBQVMsQ0FBQztBQUFBLFFBQ3ZCLFdBQVcsTUFBTSxRQUFRQSxJQUFHLEdBQUc7QUFDN0IsY0FBSSxDQUFDQSxLQUFJLE1BQU0sQ0FBQyxLQUFLLEdBQUcsUUFBUSxRQUFRLElBQUksQ0FBQyxDQUFDLEdBQUc7QUFDL0Msa0JBQU0sTUFBTSxrQ0FBa0NBLElBQUcsRUFBRTtBQUFBLFVBQ3JEO0FBQ0Esb0JBQVUsRUFBRSxLQUFLQSxLQUFJLENBQUMsR0FBRyxRQUFRQSxLQUFJLENBQUMsR0FBRyxNQUFNQSxLQUFJLENBQUMsR0FBRyxPQUFPQSxLQUFJLENBQUMsR0FBRyxPQUFPQSxLQUFJLENBQUMsR0FBRyxNQUFNQSxLQUFJLENBQUMsRUFBRTtBQUNsRyxnQkFBTSxXQUFXO0FBQUEsWUFDZixDQUFDLFNBQVMsVUFBVSxTQUFTLENBQUM7QUFBQSxZQUM5QixDQUFDLGFBQWEsY0FBYyxXQUFXO0FBQUEsWUFDdkM7QUFBQSxZQUNBLENBQUMsYUFBYSxjQUFjLFdBQVc7QUFBQSxZQUN2Q0EsS0FBSSxDQUFDO0FBQUEsVUFDUDtBQUNBLHFCQUFXLFNBQVMsQ0FBQztBQUNyQixzQkFBWSxTQUFTLENBQUM7QUFDdEIscUJBQVcsU0FBUyxDQUFDO0FBQUEsUUFDdkIsV0FBV0EsU0FBUSxjQUFjO0FBRS9CLHFCQUFXLEtBQUssS0FBSyxVQUFVLFdBQVc7QUFDMUMsc0JBQVksS0FBSyxLQUFLLFdBQVcsWUFBWTtBQUM3QyxxQkFBVyxLQUFLLEtBQUssVUFBVSxXQUFXO0FBQzFDLGdCQUFNLGlCQUFpQixXQUFXLEtBQUssY0FBYyxjQUFjO0FBQ25FLGdCQUFNLGtCQUFrQixZQUFZLEtBQUssZUFBZSxlQUFlO0FBQ3ZFLGdCQUFNLGlCQUFpQixXQUFXLEtBQUssY0FBYyxjQUFjO0FBQ25FLGdCQUFNLFFBQVEsS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQzFDLGdCQUFNLE9BQU8sZ0JBQWdCO0FBQzdCLGdCQUFNLE1BQU0sS0FBSyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLGdCQUFNLFNBQVMsaUJBQWlCO0FBQ2hDLGdCQUFNLE9BQU8sS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ3pDLGdCQUFNLFFBQVEsZ0JBQWdCO0FBRTlCLG9CQUFVLEVBQUUsS0FBSyxRQUFRLE1BQU0sT0FBTyxPQUFPLEtBQUs7QUFBQSxRQUNwRCxPQUFPO0FBQ0wsZ0JBQU0sTUFBTSw4QkFBOEJBLElBQUcsRUFBRTtBQUFBLFFBQ2pEO0FBQ0EsZUFBTyxFQUFFLFNBQVMsVUFBVSxXQUFXLFNBQVM7QUFBQSxNQUNsRDtBQXdDTyxNQUFNLG9CQUFvQixDQUMvQixTQUNBLGFBQ0EsU0FDQSxXQUNBQSxNQUNBLFlBQVksT0FDWixhQUErQyxtQkFDaEM7QUFDZixZQUFJLFdBQVcsU0FBUyxVQUFVLFNBQVM7QUFDM0MsWUFBSSxlQUFlLGdCQUFnQjtBQUNqQyxXQUFDLFdBQVcsU0FBUyxVQUFVLFNBQVMsVUFBVSxJQUFJO0FBQUEsUUFDeEQsV0FBVyxlQUFlLGlCQUFpQjtBQUN6QyxXQUFDLFdBQVcsWUFBWSxTQUFTLFVBQVUsT0FBTyxJQUFJO0FBQUEsUUFDeEQsT0FBTztBQUNMLGdCQUFNLElBQUksTUFBTSxzQkFBc0IsVUFBVSxFQUFFO0FBQUEsUUFDcEQ7QUFDQSxjQUFNLENBQUMsZ0JBQWdCLEVBQUUsYUFBYSxjQUFjLFdBQVcsSUFBSTtBQUVuRSxjQUFNLENBQUMsYUFBYSxjQUFjLFdBQVcsSUFBSSxpQkFBaUIsT0FBTztBQUN6RSxjQUFNLENBQUMsZUFBZSxnQkFBZ0IsYUFBYSxJQUFJLGlCQUFpQixTQUFTO0FBRWpGLGNBQU0sdUJBQXVCLHVCQUF1QixhQUFhLGFBQWE7QUFDOUUsY0FBTSx3QkFBd0IsdUJBQXVCLGNBQWMsY0FBYztBQUNqRixjQUFNLHVCQUF1Qix1QkFBdUIsYUFBYSxhQUFhO0FBQzlFLGNBQU0sRUFBRSxTQUFTLFVBQVUsV0FBVyxTQUFTLElBQUk7QUFBQSxVQUNqREE7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBRUEsY0FBTSxjQUFjLFlBQVksaUJBQWlCLGFBQWE7QUFFOUQsWUFBSSxXQUFxRCxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQztBQUN2RSxZQUFJLGVBQWUsaUJBQWlCO0FBQ2xDLHFCQUFXLENBQUMsV0FBVyxhQUFhLFVBQVUsV0FBVyxRQUFRO0FBQUEsUUFDbkUsV0FBVyxlQUFlLGdCQUFnQjtBQUN4QyxxQkFBVyxDQUFDLFdBQVcsVUFBVSxXQUFXLFVBQVUsV0FBVztBQUFBLFFBQ25FO0FBRUEsZUFBTztBQUFBLFVBQ0w7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLCtCQUErQixDQUMxQyxRQUNBLFlBQ0EsYUFDQSxZQUNBLE1BQ0EsZUFDZ0I7QUFDaEIsY0FBTSxnQkFBZ0IsZUFBZTtBQUNyQyxjQUFNLGFBQWEsZ0JBQWdCLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxJQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQztBQUV2RSxjQUFNLFNBQVM7QUFDZixjQUFNLGdCQUEwQyxDQUFDLElBQUksR0FBRyxDQUFDO0FBQ3pELGNBQU0saUJBQWlCLEVBQUUsR0FBRyxZQUFZLElBQUksQ0FBQyxHQUFHLE1BQU0sQ0FBQyxFQUFFO0FBQ3pELGNBQU0sV0FBVyxDQUFDLEtBQUssS0FBSyxhQUFhLGVBQWUsRUFBRSxJQUFJLENBQUMsTUFBTSxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksY0FBYyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUM7QUFFL0csa0JBQVUsV0FBVyxNQUFNLG9DQUFvQyxRQUFRLEVBQUU7QUFFekUsY0FBTSxtQkFBbUIsU0FBVSxpQkFBaUIsYUFBYSxNQUFNLElBQUksSUFBSSxJQUFLO0FBQ3BGLGNBQU0sYUFBYSxVQUFVLEtBQUssV0FBVztBQUM3QyxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sS0FBSztBQUFBLFVBQ3BDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVyxRQUFRO0FBQUEsVUFDbEQsRUFBRSx1QkFBdUIsTUFBTSxXQUFXLFVBQVU7QUFBQSxRQUN0RDtBQUNBLHFDQUE2QixZQUFZLGVBQWU7QUFDeEQsd0JBQWdCLEtBQUssR0FBRywyQkFBMkIsT0FBTyxDQUFDLEVBQUUsTUFBTSxPQUFPLENBQUMsRUFBRSxJQUFJLENBQUM7QUFDbEYsY0FBTSxvQkFBd0QsQ0FBQyxRQUFRLE1BQU07QUFDN0UsY0FBTSxVQUFVLE9BQU8sV0FBVztBQUNsQyxZQUFJLFNBQVM7QUFDWCwwQkFBZ0IsS0FBSyxHQUFHLDJCQUEyQixPQUFPLENBQUMsRUFBRSxJQUFJLENBQUM7QUFDbEUsNEJBQWtCLEtBQUssTUFBTTtBQUFBLFFBQy9CO0FBQ0Esd0JBQWdCLEtBQUssR0FBRywyQkFBMkIsV0FBVyxDQUFDO0FBRS9ELGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQ3RELGdCQUFNLFdBQThCO0FBQUEsWUFDbEMsRUFBRSxNQUFNLGVBQWUsTUFBTSxNQUFNO0FBQUEsWUFDbkMsRUFBRSxNQUFNLGVBQWUsTUFBTSxPQUFPLFFBQVEsV0FBVyxPQUFPO0FBQUEsWUFDOUQsRUFBRSxNQUFNLFFBQVEsTUFBTSxPQUFPLFFBQVEsS0FBSyxPQUFPO0FBQUEsWUFDakQsRUFBRSxNQUFNLFdBQVcsTUFBTSxPQUFPLFFBQVEsV0FBVyxRQUFRLE9BQU87QUFBQSxZQUNsRSxFQUFFLE1BQU0sYUFBYSxNQUFNLE9BQU8sUUFBUSxXQUFXLFVBQVUsT0FBTztBQUFBLFVBQ3hFO0FBQ0EsbUNBQXlCLFlBQVksUUFBUTtBQUU3QyxnQkFBTSxhQUFhLFNBQVMsSUFBSTtBQUNoQyxnQkFBTSxJQUFJLDRCQUE0QixPQUFPLENBQUMsRUFBRSxRQUFRO0FBRXhELGdCQUFNLElBQUk7QUFBQSxZQUNSO0FBQUEsWUFDQSxPQUFPLENBQUMsRUFBRTtBQUFBLFlBQ1YsT0FBTyxDQUFDLEVBQUUsS0FBSztBQUFBLFlBQ2YscUJBQXFCLElBQUksSUFBSTtBQUFBLFVBQy9CO0FBQ0EsZ0JBQU0sSUFBSSxjQUFjLEtBQUssT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLFFBQVEsVUFBVTtBQUNsRixnQkFBTSxpQkFBaUIsQ0FBQyxHQUFHLENBQUM7QUFDNUIsZ0JBQU0sU0FBUyxlQUFlLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxZQUFZLFFBQVEsVUFBVTtBQUMxRixjQUFJLG1CQUFtQjtBQUN2QixjQUFJLFNBQVM7QUFDWCxrQkFBTSxPQUFPLGNBQWMsUUFBUSxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLEtBQUssUUFBUSxVQUFVO0FBQ3hGLDJCQUFlLEtBQUssSUFBSTtBQUN4QixnQ0FBb0I7QUFBQSw4REFDb0MsU0FBUyxRQUFRLENBQUMsTUFBTSxDQUFDO0FBQUEsd0JBQy9ELGdCQUFnQixhQUFhLFVBQVUsR0FBRyxDQUFDLElBQUksYUFBYSxVQUFVLEdBQUcsQ0FBQyxDQUFDLEdBQ3ZGLFNBQVMsUUFBUSxFQUNuQjtBQUFBO0FBQUEsVUFFTjtBQUNBLGdCQUFNLFVBQVUsWUFBWSxrQkFBa0IsQ0FBQztBQUMvQyxnQkFBTSxrQkFBa0IscUJBQXFCLFlBQVksU0FBUyxDQUFDO0FBRW5FLGlCQUFPO0FBQUEsY0FDRyxnQkFBZ0I7QUFBQTtBQUFBO0FBQUEsdUJBR1AsRUFBRSxhQUFhLFVBQVUsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBLHVCQUkxQixFQUFFLGFBQWEsVUFBVSxDQUFDO0FBQUE7QUFBQSxZQUVyQyxhQUFhLGlCQUFpQixRQUFRLEVBQUUsaUJBQWlCLEdBQUcsZ0JBQWdCLE1BQU0sQ0FBQztBQUFBLFlBQ25GLGFBQWEsVUFBVSxDQUFDO0FBQUEsWUFDeEIsYUFBYSxzQ0FBc0Msc0JBQXNCLENBQUM7QUFBQSw2QkFDekQsT0FBTyxnQkFBZ0IsWUFBWSxDQUFDO0FBQUEsNEJBQ3JDLGFBQWEsVUFBVSxHQUFHLEVBQUUsSUFBSSxDQUFDO0FBQUEseUJBRTdDLGdCQUFnQixhQUFhLFVBQVUsRUFBRSxPQUFPLEdBQUcsRUFBRSxJQUFJLElBQUksYUFBYSxVQUFVLEdBQUcsRUFBRSxJQUFJLENBQy9GO0FBQUEsMkNBRUUsZ0JBQWdCLGFBQWEsVUFBVSxHQUFHLEVBQUUsSUFBSSxJQUFJLGFBQWEsVUFBVSxHQUFHLEVBQUUsSUFBSSxDQUN0RjtBQUFBLGdCQUNFLGdCQUFnQixhQUFhLFVBQVUsR0FBRyxFQUFFLElBQUksSUFBSSxhQUFhLFVBQVUsR0FBRyxFQUFFLElBQUksQ0FBQztBQUFBLGdCQUVyRixnQkFBZ0IsYUFBYSxVQUFVLEdBQUcsRUFBRSxJQUFJLElBQUksYUFBYSxVQUFVLEdBQUcsRUFBRSxJQUFJLENBQ3RGO0FBQUE7QUFBQTtBQUFBO0FBQUEsOEJBS0UsZ0JBQ0ksYUFBYSxvQkFBb0IsR0FBRyxFQUFFLElBQUksSUFDMUMsYUFBYSxvQkFBb0IsR0FBRyxFQUFFLElBQUksQ0FDaEQ7QUFBQSw4QkFFRSxnQkFDSSxhQUFhLG9CQUFvQixHQUFHLEVBQUUsSUFBSSxJQUMxQyxhQUFhLG9CQUFvQixHQUFHLEVBQUUsSUFBSSxDQUNoRDtBQUFBLDhCQUVFLGdCQUNJLGFBQWEsb0JBQW9CLEdBQUcsRUFBRSxJQUFJLElBQzFDLGFBQWEsb0JBQW9CLEdBQUcsRUFBRSxJQUFJLENBQ2hEO0FBQUEsOEJBRUUsZ0JBQ0ksYUFBYSxvQkFBb0IsR0FBRyxFQUFFLElBQUksSUFDMUMsYUFBYSxvQkFBb0IsR0FBRyxFQUFFLElBQUksQ0FDaEQ7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsd0JBeUJVLGdCQUNJO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQ0FNQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsNkJBTU47QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsMEJBVUksZ0JBQ0k7QUFBQSw0RUFFQTtBQUFBLHlFQUVOO0FBQUE7QUFBQSx3QkFHQSxnQkFDSTtBQUFBO0FBQUE7QUFBQSwwQkFJQTtBQUFBO0FBQUE7QUFBQSxxQkFJTjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSx3QkFPRSxnQkFDSTtBQUFBO0FBQUE7QUFBQTtBQUFBLDBCQUtBO0FBQUE7QUFBQTtBQUFBO0FBQUEscUJBS047QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFVTixVQUFVLGtEQUFrRCxFQUFFO0FBQUEsZ0JBQzlELGVBQWU7QUFBQTtBQUFBO0FBQUEsUUFHN0I7QUFDQSxlQUFPO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixhQUFhLEVBQUUsTUFBTSxHQUFHLFdBQVcsUUFBUSxJQUFJLGFBQWEsSUFBSSxnQkFBZ0IsSUFBSSxPQUFPLElBQUksa0JBQWtCO0FBQUEsVUFDakgsWUFBWSxPQUFPO0FBQUEsWUFDakIsU0FBUyxDQUFDLEVBQUUsTUFBTSxhQUFhLFVBQVUsT0FBTyxDQUFDLEVBQUUsU0FBUyxDQUFDO0FBQUEsWUFDN0QsZUFBZSxFQUFFLEdBQUcsU0FBUyxDQUFDLEdBQUcsR0FBRyxTQUFTLENBQUMsR0FBRyxHQUFHLFNBQVMsQ0FBQyxFQUFFO0FBQUEsWUFDaEU7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBQUE7QUFBQTs7O0FDdmZBLE1Bd0JhLDhCQTJJQTtBQW5LYjtBQUFBO0FBQUE7QUFHQTtBQUVBO0FBR0E7QUFVQTtBQU1PLE1BQU0sK0JBQStCLENBQzFDLFFBQ0EsWUFDQSxhQUNBLCtCQUNnQjtBQUNoQixjQUFNLFVBQVUsT0FBTyxTQUFTO0FBQ2hDLGNBQU0sY0FBYyxVQUFVLGdDQUFnQztBQUM5RCxjQUFNLFNBQVMsT0FBTyxDQUFDLEVBQUU7QUFDekIsY0FBTSxTQUFTLE9BQU8sQ0FBQyxFQUFFO0FBRXpCLGNBQU0sZ0JBQWdCLFdBQVcsV0FBVztBQUM1QyxjQUFNLGlCQUFpQixnQkFBZ0IsWUFBWSxDQUFDLElBQUksWUFBWSxDQUFDO0FBQ3JFLGNBQU0seUJBQXlCLGlCQUFpQixXQUFXO0FBQzNELGNBQU0sYUFBYSxpQkFBaUIsMEJBQTBCLElBQUksaUJBQWlCLGNBQWMsSUFBSTtBQUNyRyxjQUFNLGFBQWEsVUFBVSxLQUFLLFdBQVcsSUFBSTtBQUVqRCxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVyxVQUFVO0FBQUEsVUFDcEQsRUFBRSx1QkFBdUIsTUFBTSxDQUFDLFdBQVcsUUFBUSxDQUFDLEdBQUcsV0FBVyxRQUFRLENBQUMsQ0FBQyxFQUFFO0FBQUEsVUFDOUUsRUFBRSx1QkFBdUIsTUFBTSxDQUFDLFdBQVcsS0FBSyxDQUFDLEdBQUcsV0FBVyxLQUFLLENBQUMsQ0FBQyxFQUFFO0FBQUEsVUFDeEUsRUFBRSx1QkFBdUIsTUFBTSx1QkFBdUI7QUFBQSxRQUN4RDtBQUNBLHFDQUE2QixZQUFZLGVBQWU7QUFDeEQsd0JBQWdCO0FBQUEsVUFDZCxHQUFHLDJCQUEyQixRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsT0FBTyxDQUFDLEdBQUcsT0FBTyxDQUFDLEdBQUcsT0FBTyxDQUFDLElBQUksVUFBVSxDQUFDO0FBQUEsUUFDakc7QUFDQSxjQUFNLG9CQUF3RCxVQUFVLENBQUMsUUFBUSxRQUFRLE1BQU0sSUFBSSxDQUFDLFFBQVEsTUFBTTtBQUNsSCx3QkFBZ0I7QUFBQSxVQUNkLEdBQUcsMkJBQTJCLENBQUMsWUFBWSxDQUFDLEdBQUcsWUFBWSxDQUFDLEdBQUcsWUFBWSxDQUFDLEdBQUcsWUFBWSxDQUFDLElBQUksVUFBVSxDQUFDO0FBQUEsUUFDN0c7QUFFQSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxnQkFBTSxTQUFTLGVBQWUsVUFBVSxPQUFPLENBQUMsRUFBRSxVQUFVLFlBQVksUUFBUSxVQUFVO0FBQzFGLGdCQUFNLFdBQVcsNEJBQTRCLE9BQU8sS0FBSyxNQUFNO0FBQy9ELGdCQUFNLGtCQUFrQixxQkFBcUIsWUFBWSxPQUFPLEtBQUssT0FBTyxRQUFRO0FBQ3BGLGdCQUFNLElBQUksY0FBYyxLQUFLLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxNQUFNO0FBQzlELGdCQUFNLElBQUksY0FBYyxLQUFLLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxRQUFRLFVBQVU7QUFDMUUsZ0JBQU0sWUFBWSxDQUFDLEdBQUcsQ0FBQztBQUN2QixjQUFJLFNBQVM7QUFDWCxzQkFBVSxLQUFLLGNBQWMsS0FBSyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQUEsVUFDbkY7QUFFQSxnQkFBTSxXQUE4QjtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxlQUFlLE1BQU0sTUFBTTtBQUFBLFlBQ25DLEVBQUUsTUFBTSxhQUFhLE1BQU0sT0FBTyxRQUFRLFdBQVcsVUFBVSxPQUFPO0FBQUEsWUFDdEUsRUFBRSxNQUFNLFdBQVcsTUFBTSxPQUFPLFFBQVEsRUFBRTtBQUFBLFlBQzFDLEVBQUUsTUFBTSxRQUFRLE1BQU0sT0FBTyxRQUFRLEVBQUU7QUFBQSxZQUN2QyxFQUFFLE1BQU0sNkJBQTZCLE1BQU0sTUFBTTtBQUFBLFVBQ25EO0FBQ0EsbUNBQXlCLFlBQVksUUFBUTtBQUU3QyxnQkFBTSxrQkFBa0IsZ0JBQ3BCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEseUJBZ0JpQixFQUFFLElBQUksU0FBUyxXQUFXLFVBQVUsZUFBZSxDQUFDO0FBQUEseUJBQ3BELEVBQUUsSUFBSSxXQUFXLFVBQVUsY0FBYyxnQkFBZ0IsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsVUFNM0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSx5QkFnQmlCLEVBQUUsSUFBSSxTQUFTLGlCQUFpQixXQUFXLFFBQVEsQ0FBQztBQUFBLHlCQUNwRCxFQUFFLElBQUksa0JBQWtCLGNBQWMsV0FBVyxRQUFRLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBTS9FLGlCQUFPO0FBQUEsSUFDUCxhQUFhLGlCQUFpQixRQUFRLEVBQUUsaUJBQWlCLEdBQUcsV0FBVyxNQUFNLENBQUM7QUFBQTtBQUFBLElBRTlFLGFBQWEsVUFBVSxDQUFDO0FBQUEsTUFDdEIsYUFBYSxzQ0FBc0Msc0JBQXNCLENBQUM7QUFBQTtBQUFBLDBCQUV0RCxPQUFPLGdCQUFnQixZQUFZLENBQUM7QUFBQTtBQUFBLDhDQUVoQixnQkFBZ0IsSUFBSSxDQUFDO0FBQUEseURBQ1YsZ0JBQWdCLElBQUksQ0FBQyxvQkFDeEUsZ0JBQWdCLElBQUksQ0FDdEI7QUFBQSwyQ0FDdUMsVUFBVTtBQUFBLDBEQUNLLGdCQUFnQixJQUFJLENBQUM7QUFBQTtBQUFBLGlCQUU5RCxPQUFPLEtBQUssS0FBSyxNQUFNLE9BQU8sS0FBSyxLQUFLO0FBQUEsTUFDbkQsZUFBZTtBQUFBLE1BQ2YsV0FBVztBQUFBLE1BQ1gsZUFBZTtBQUFBLE1BQ2YsT0FBTyxZQUFZLGNBQWMsT0FBTyxDQUFDO0FBQUE7QUFBQSxRQUU3QztBQUNBLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWEsRUFBRSxNQUFNLEdBQUcsV0FBVyxRQUFRLElBQUksVUFBVSxJQUFJLGtCQUFrQjtBQUFBLFVBQy9FLFlBQVksT0FBTztBQUFBLFlBQ2pCLFNBQVM7QUFBQSxjQUNQO0FBQUEsZ0JBQ0UsTUFBTSw2QkFBNkIsMkJBQTJCLFdBQVcsSUFBSTtBQUFBLGdCQUM3RSxVQUFVLE9BQU8sQ0FBQyxFQUFFO0FBQUEsY0FDdEI7QUFBQSxZQUNGO0FBQUEsWUFDQSxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxhQUFhO0FBQUE7QUFBQSxZQUF1QixFQUFFO0FBQUEsWUFDcEU7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSx3Q0FBd0MsQ0FDbkQsUUFDQSxZQUNBLGFBQ0EsK0JBQ2dCO0FBQ2hCLGNBQU0sVUFBVSxPQUFPLFNBQVM7QUFDaEMsY0FBTSxhQUFhLGlCQUFpQixZQUFZLENBQUMsQ0FBQztBQUNsRCxjQUFNLGVBQWUsaUJBQWlCLFlBQVksQ0FBQyxDQUFDO0FBQ3BELGNBQU0sYUFBYSxVQUFVLEtBQUssV0FBVyxJQUFJLGFBQWE7QUFDOUQsY0FBTSxTQUFTLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLElBQUksVUFBVTtBQUN2RyxjQUFNLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsSUFBSSxVQUFVO0FBQ3ZHLGNBQU0sc0JBQXNCLENBQUMsWUFBWSxDQUFDLEdBQUcsWUFBWSxDQUFDLEdBQUcsWUFBWSxDQUFDLEdBQUcsWUFBWSxDQUFDLElBQUksVUFBVTtBQUV4RyxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUscUJBQXNCLE1BQU0sQ0FBQyxXQUFXLFFBQVEsQ0FBQyxHQUFHLFdBQVcsUUFBUSxDQUFDLENBQUMsRUFBRTtBQUFBLFVBQzdFLEVBQUUscUJBQXNCLE1BQU0sQ0FBQyxXQUFXLEtBQUssQ0FBQyxHQUFHLFdBQVcsS0FBSyxDQUFDLENBQUMsRUFBRTtBQUFBLFFBQ3pFO0FBQ0EscUNBQTZCLFlBQVksZUFBZTtBQUN4RCx3QkFBZ0IsS0FBSyxHQUFHLDJCQUEyQixRQUFRLFFBQVEsbUJBQW1CLENBQUM7QUFDdkYsY0FBTSxXQUFXLGVBQWUsS0FBSyxXQUFXLFFBQVEsQ0FBQyxJQUFJLE9BQU8sQ0FBQztBQUNyRSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxnQkFBTSxTQUFTLGVBQWUsVUFBVSxPQUFPLENBQUMsRUFBRSxVQUFVLG9CQUFvQixRQUFRLFVBQVU7QUFDbEcsZ0JBQU0sV0FBVyw0QkFBNEIsT0FBTyxLQUFLLE1BQU07QUFDL0QsZ0JBQU0sa0JBQWtCLHFCQUFxQixZQUFZLE9BQU8sS0FBSyxPQUFPLFFBQVE7QUFDcEYsZ0JBQU0sSUFBSSxjQUFjLEtBQUssT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLFFBQVEsVUFBVTtBQUMxRSxnQkFBTSxJQUFJLGNBQWMsS0FBSyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sUUFBUSxVQUFVO0FBQzFFLGdCQUFNLFlBQVksQ0FBQyxHQUFHLENBQUM7QUFDdkIsY0FBSSxTQUFTO0FBQ1gsc0JBQVUsS0FBSyxjQUFjLEtBQUssT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUFBLFVBQ25GO0FBQ0EsZ0JBQU0sY0FBYyxVQUFVLGdDQUFnQztBQUM5RCxnQkFBTSxXQUE4QjtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxlQUFlLE1BQU0sTUFBTTtBQUFBLFlBQ25DLEVBQUUsTUFBTSxXQUFXLE1BQU0sT0FBTyxRQUFRLEVBQUU7QUFBQSxZQUMxQyxFQUFFLE1BQU0sUUFBUSxNQUFNLE9BQU8sUUFBUSxFQUFFO0FBQUEsVUFDekM7QUFDQSxtQ0FBeUIsWUFBWSxRQUFRO0FBQzdDLGlCQUFPO0FBQUEsSUFDUCxhQUFhLGlCQUFpQixRQUFRLEVBQUUsaUJBQWlCLEdBQUcsV0FBVyxNQUFNLENBQUM7QUFBQSxJQUM5RSxhQUFhLFVBQVUsQ0FBQztBQUFBLE1BQ3RCLGFBQWEsc0NBQXNDLHNCQUFzQixDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUEsOENBSWxDLFlBQVk7QUFBQSxvQ0FDdEIsWUFBWTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHdCQU94QixFQUFFLEtBQUssS0FBSyxLQUFLLE9BQU87QUFBQSx3QkFDeEIsT0FBTyxLQUFLLEtBQUssS0FBSyxZQUFZO0FBQUE7QUFBQTtBQUFBLDhDQUdaLE9BQU8sQ0FBQyxDQUFDO0FBQUE7QUFBQTtBQUFBLDhCQUd6QixPQUFPO0FBQUE7QUFBQTtBQUFBLDBCQUdYLEVBQUUsSUFBSSxTQUFTLGlCQUFpQixnQkFBZ0IsZUFBZSxDQUFDO0FBQUE7QUFBQSwwQkFFaEUsRUFBRSxLQUFLLEtBQUs7QUFBQTtBQUFBO0FBQUEsZ0RBR1UsT0FBTyxDQUFDLENBQUM7QUFBQSx3QkFDakMsRUFBRSxJQUFJLFlBQVksV0FBVyxLQUFLLGdCQUFnQixDQUFDO0FBQUEsaUNBQzFDLFlBQVk7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSwyQkFPbEIsWUFBWTtBQUFBO0FBQUEsUUFFL0IsV0FBVztBQUFBLFFBQ1gsZUFBZTtBQUFBLFFBQ2YsT0FBTyxJQUFJLFNBQVMsT0FBTyxXQUFXLGtCQUFrQixPQUFPLENBQUM7QUFBQTtBQUFBO0FBQUEsUUFHdEU7QUFFQSxlQUFPO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixhQUFhO0FBQUEsWUFDWCxNQUFNLEdBQUcsV0FBVyxRQUFRLElBQUksVUFBVSxJQUFJLFlBQVksSUFBSSxPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsQ0FBQztBQUFBLFlBQy9GLG1CQUFtQixVQUFVLENBQUMsUUFBUSxRQUFRLE1BQU0sSUFBSSxDQUFDLFFBQVEsTUFBTTtBQUFBLFVBQ3pFO0FBQUEsVUFDQSxZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTO0FBQUEsY0FDUDtBQUFBLGdCQUNFLE1BQU0sNkJBQTZCLDJCQUEyQixXQUFXLElBQUk7QUFBQSxnQkFDN0UsVUFBVSxPQUFPLENBQUMsRUFBRTtBQUFBLGNBQ3RCO0FBQUEsWUFDRjtBQUFBLFlBQ0EsZUFBZSxFQUFFLEdBQUcsS0FBSztBQUFBLGNBQUssYUFBYTtBQUFBO0FBQUEsWUFBdUIsRUFBRTtBQUFBLFlBQ3BFO0FBQUEsVUFDRjtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQzVRQSxNQWdCYSxzQkFtQ1AsMEJBRUFDLGlCQWtEQSwyQkE0Qk8scUJBMEJQLFFBc01BLFFBOEJBLFFBeUJPO0FBMVpiO0FBQUE7QUFBQTtBQUlBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFTyxNQUFNLHVCQUF1QixDQUNsQyxZQUNBLGFBQ0EsV0FDQSxZQUNBLFNBQ0Esa0JBQ2E7QUFDYixjQUFNLFlBQVksV0FBVyxDQUFDO0FBQzlCLGNBQU0sb0JBQW9CLFdBQVcsTUFBTSxnQkFBZ0IsSUFBSSxHQUFHLGdCQUFnQixJQUFJLENBQUM7QUFDdkYsY0FBTSxjQUFjLGtCQUFrQjtBQUN0QyxjQUFNLGNBQWMsWUFBWSxDQUFDO0FBQ2pDLGNBQU0scUJBQXFCLFlBQVksTUFBTSxDQUFDO0FBQzlDLGNBQU0scUJBQXFCLG1CQUFtQixJQUFJLENBQUMsR0FBRyxNQUFNLEtBQUssSUFBSSxNQUFNLFVBQVUsQ0FBQyxJQUFJLEVBQUU7QUFDNUYsY0FBTSwyQkFBMkIsa0JBQWtCLElBQUksQ0FBQyxHQUFHLE1BQU0sSUFBSSxXQUFXLENBQUMsSUFBSSxXQUFXLElBQUksV0FBVyxDQUFDO0FBQ2hILGNBQU0sY0FBYyx5QkFBeUI7QUFBQSxVQUFJLENBQUMsR0FBRyxNQUNuRCxLQUFLLE9BQU8sSUFBSSxtQkFBbUIsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxLQUFLLFFBQVEsQ0FBQyxDQUFDO0FBQUEsUUFDbEU7QUFDQSxvQkFBWSxPQUFPLEdBQUcsR0FBRyxTQUFTO0FBQ2xDLG9CQUFZLE9BQU8sZ0JBQWdCLElBQUksR0FBRyxHQUFHLFdBQVc7QUFDeEQsZUFBTztBQUFBLE1BQ1Q7QUFjQSxNQUFNLDJCQUEyQixDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7QUFFNUMsTUFBTUEsa0JBQWlCLENBQUMsUUFBK0IsZUFBcUM7QUFHMUYsWUFBSSxDQUFDLFVBQVcsT0FBTyxXQUFXLEtBQUssT0FBTyxXQUFXLEdBQUk7QUFDM0QsZ0JBQU0sSUFBSSxNQUFNLDZCQUE2QjtBQUFBLFFBQy9DO0FBRUEsWUFBSSxPQUFPLENBQUMsRUFBRSxLQUFLLFNBQVMsR0FBRztBQUM3QixnQkFBTSxJQUFJLE1BQU0sa0NBQWtDO0FBQUEsUUFDcEQ7QUFFQSxZQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssV0FBVyxPQUFPLENBQUMsRUFBRSxLQUFLLFFBQVE7QUFDbkQsZ0JBQU0sSUFBSSxNQUFNLDhDQUE4QztBQUFBLFFBQ2hFO0FBR0EsY0FBTSxjQUFjLE9BQU8sQ0FBQyxFQUFFLEtBQUssV0FBVyxXQUFXLFNBQVMsT0FBTyxDQUFDLEVBQUUsS0FBSyxTQUFTLElBQUksQ0FBQztBQUMvRixjQUFNLGtCQUFrQixPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsSUFBSSxXQUFXO0FBQ3ZELFlBQUksZ0JBQWdCLGlCQUFpQjtBQUNuQyxnQkFBTSxJQUFJLE1BQU0sbURBQW1EO0FBQUEsUUFDckU7QUFHQSxZQUFJLE9BQU8sV0FBVyxNQUFNLE9BQU8sQ0FBQyxFQUFFLEtBQUssV0FBVyxLQUFLLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxNQUFNLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxJQUFJO0FBQ25HLGdCQUFNLElBQUksTUFBTSxjQUFjO0FBQUEsUUFDaEM7QUFFQSxjQUFNLGNBQWMsT0FBTyxDQUFDLEVBQUUsS0FBSyxTQUFTO0FBRTVDLFlBQUksV0FBVyxVQUFVLFdBQVcsYUFBYTtBQUMvQyxnQkFBTSxJQUFJLE1BQU0sdUJBQXVCLFdBQVcsR0FBRztBQUFBLFFBQ3ZEO0FBR0EsWUFBSSxXQUFXLFFBQVEsV0FBVyxhQUFhO0FBQzdDLGdCQUFNLElBQUksTUFBTSxxQkFBcUIsV0FBVyxHQUFHO0FBQUEsUUFDckQ7QUFHQSxZQUFJLFdBQVcsS0FBSyxXQUFXLGNBQWMsR0FBRztBQUM5QyxnQkFBTSxJQUFJLE1BQU0sa0JBQWtCLGNBQWMsQ0FBQyxHQUFHO0FBQUEsUUFDdEQ7QUFJQSxZQUFJLFdBQVcsWUFBWSxXQUFXLEtBQUssV0FBVyxZQUFZLFdBQVcsT0FBTyxDQUFDLEVBQUUsS0FBSyxTQUFTLEdBQUc7QUFDdEcsZ0JBQU0sSUFBSSxNQUFNLHNCQUFzQjtBQUFBLFFBQ3hDO0FBQUEsTUFDRjtBQUVBLE1BQU0sNEJBQTRCLENBQTJCLFlBQWUsV0FBcUM7QUFDL0csY0FBTSxjQUFjLFdBQVcsWUFBWSxNQUFNO0FBRWpELFlBQUksWUFBWSxTQUFTLE9BQU8sQ0FBQyxFQUFFLEtBQUssU0FBUyxHQUFHO0FBQ2xELHNCQUFZLEtBQUssR0FBRyxNQUFNLE9BQU8sQ0FBQyxFQUFFLEtBQUssU0FBUyxJQUFJLFlBQVksTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQUEsUUFDbkY7QUFDQSxpQkFBUyxJQUFJLEdBQUcsSUFBSSxPQUFPLENBQUMsRUFBRSxLQUFLLFFBQVEsRUFBRSxHQUFHO0FBQzlDLGNBQUksWUFBWSxJQUFJLENBQUMsTUFBTSxHQUFHO0FBQzVCLHdCQUFZLElBQUksQ0FBQyxJQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQztBQUFBLFVBQ3ZDO0FBQUEsUUFDRjtBQUNBLGNBQU0sT0FBTyxXQUFXLEtBQUssTUFBTTtBQUNuQyxxQkFBYTtBQUFBLFVBQ1gsT0FBTyxDQUFDLEVBQUU7QUFBQSxVQUNWLFdBQVc7QUFBQSxVQUNYLFdBQVc7QUFBQSxVQUNYO0FBQUEsVUFDQTtBQUFBLFVBQ0EsV0FBVyxXQUFXO0FBQUEsVUFDdEIsV0FBVztBQUFBLFFBQ2I7QUFHQSxjQUFNLGdCQUFtQixPQUFPLE9BQU8sQ0FBQyxHQUFHLFVBQVU7QUFDckQsZUFBTyxPQUFPLGVBQWUsRUFBRSxhQUFhLEtBQUssQ0FBQztBQUNsRCxlQUFPO0FBQUEsTUFDVDtBQUVPLE1BQU0sc0JBQXNCLENBQUMsZUFBd0Q7QUFDMUYsY0FBTSx1QkFBdUIsa0NBQWtDLFVBQVU7QUFFekUsY0FBTSxTQUFTLFdBQVc7QUFDMUIsY0FBTSxVQUFVLENBQUMsVUFBVSxTQUFTLGNBQWMsWUFBWSxFQUFFLFdBQVcsUUFBa0I7QUFDN0YsY0FBTSxZQUFZLFdBQVc7QUFDN0IsY0FBTSxRQUFRLFdBQVc7QUFDekIsY0FBTSxjQUFjLFdBQVc7QUFDL0IsY0FBTSxPQUFPLFdBQVc7QUFDeEIsY0FBTSxVQUFVLFdBQVc7QUFDM0IsY0FBTSxXQUFZLFdBQVcsV0FBNkI7QUFFMUQsZUFBTztBQUFBLFVBQ0w7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQSxHQUFHO0FBQUEsVUFDSCxVQUFVLEdBQUcsV0FBVyxNQUFNLElBQUkscUJBQXFCLFVBQVU7QUFBQSxRQUNuRTtBQUFBLE1BQ0Y7QUFFQSxNQUFNLFNBQVMsQ0FDYixTQUNBLFFBQ0EsWUFDQSwrQkFDUztBQUlULGNBQU0saUJBQWlCLFdBQVcsV0FBVztBQUM3QyxjQUFNLGNBQWM7QUFBQSxVQUNsQixPQUFPLENBQUMsRUFBRTtBQUFBLFVBQ1YsT0FBTyxDQUFDLEVBQUU7QUFBQSxVQUNWLFdBQVc7QUFBQSxVQUNYLFdBQVc7QUFBQSxVQUNYLFdBQVc7QUFBQSxVQUNYO0FBQUEsUUFDRjtBQUNBLFlBQUksV0FBVyxVQUFVLEdBQUc7QUFDMUIsZ0JBQU1DLGNBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUM3QixjQUFJLGdCQUFnQjtBQUNsQixrQkFBTUMsb0JBQ0gsUUFBUSxpQkFBaUIsTUFDMUIsUUFBUSxRQUFRLDJCQUEyQixPQUFPLENBQUMsR0FBRyx3QkFBd0IsR0FBRztBQUFBLGNBQy9FLFFBQVEsQ0FBQyxDQUFDO0FBQUEsY0FDVixTQUFTLENBQUMsV0FBVyxXQUFXLEtBQUssRUFBRTtBQUFBLFlBQ3pDLENBQUMsRUFBRSxDQUFDO0FBQ04sZ0JBQUksV0FBVyxZQUFZLENBQUMsUUFBUSxpQkFBaUIsSUFBSTtBQUN2RCxzQkFBUSxpQkFBaUIsS0FBS0E7QUFBQSxZQUNoQztBQUNBLFlBQUFELFlBQVcsS0FBS0MsaUJBQWdCO0FBQUEsVUFDbEMsT0FBTztBQUNMLFlBQUFELFlBQVcsS0FBSyxPQUFPLENBQUMsQ0FBQztBQUFBLFVBQzNCO0FBQ0EsY0FBSSxPQUFPLFdBQVcsR0FBRztBQUN2QixZQUFBQSxZQUFXLEtBQUssT0FBTyxDQUFDLENBQUM7QUFBQSxVQUMzQjtBQUtBLGdCQUFNLDZCQUE2QixDQUFDLFFBQVEsWUFBWSxlQUFlLFFBQVE7QUFDL0UsY0FDRSw4QkFDQSxrQkFDQSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsTUFBTSxXQUFXLFNBQ2pDLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxNQUFNLEtBQ3RCLFdBQVcsVUFBVSxDQUFDLE1BQU0sS0FDNUIsV0FBVyxVQUFVLENBQUMsTUFBTSxHQUM1QjtBQUNBLG9CQUFRO0FBQUEsY0FDTixzQ0FBc0NBLGFBQVksWUFBWSxhQUFhLDBCQUEwQjtBQUFBLGNBQ3JHLEVBQUUsUUFBUUEsWUFBVztBQUFBLFlBQ3ZCO0FBQUEsVUFDRixPQUFPO0FBQ0wsb0JBQVEsUUFBUSw2QkFBNkJBLGFBQVksWUFBWSxhQUFhLDBCQUEwQixHQUFHO0FBQUEsY0FDN0csUUFBUUE7QUFBQSxZQUNWLENBQUM7QUFBQSxVQUNIO0FBQ0E7QUFBQSxRQUNGO0FBRUEsY0FBTSxVQUFVLE9BQU8sV0FBVztBQUNsQyxjQUFNLGNBQWMsT0FBTyxDQUFDLEVBQUUsS0FBSyxpQkFBaUIsSUFBSSxDQUFDO0FBQ3pELGNBQU0sYUFBYSxPQUFPLENBQUMsRUFBRSxLQUFLLGlCQUFpQixJQUFJLENBQUM7QUFDeEQsY0FBTSxnQkFBZ0IsT0FBTyxDQUFDLEVBQUUsS0FBSyxpQkFBaUIsSUFBSSxDQUFDO0FBQzNELGNBQU0sZUFBZSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUM7QUFDckMsY0FBTSxjQUFjLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQztBQUVwQyxjQUFNLFlBQVksWUFBWSxpQkFBaUIsSUFBSSxDQUFDO0FBQ3BELGNBQU0sV0FBVyxZQUFZLGlCQUFpQixJQUFJLENBQUM7QUFDbkQsY0FBTSxjQUFjLFlBQVksaUJBQWlCLElBQUksQ0FBQztBQUV0RCxjQUFNLFdBQ0osa0JBQ0EsaUJBQWlCLGVBQ2pCLGdCQUFnQixjQUNoQixXQUFXLEtBQUssQ0FBQyxNQUFNLEtBQ3ZCLFdBQVcsS0FBSyxDQUFDLE1BQU07QUFDekIsWUFDRSxZQUNDLGlCQUFpQixLQUNoQixnQkFBZ0IsS0FDaEIsV0FBVyxVQUFVLENBQUMsTUFBTSxLQUM1QixXQUFXLFVBQVUsQ0FBQyxNQUFNLEtBQzVCLFdBQVcsUUFBUSxDQUFDLE1BQU0sS0FDMUIsV0FBVyxRQUFRLENBQUMsTUFBTSxLQUMxQixXQUFXLEtBQUssQ0FBQyxNQUFNLEtBQ3ZCLFdBQVcsS0FBSyxDQUFDLE1BQU0sR0FDekI7QUFFQSxnQkFBTSxRQUFRLFlBQVksQ0FBQztBQUMzQixjQUFJLFdBQVcsV0FBVztBQUMxQixnQkFBTSxlQUFlLENBQUM7QUFDdEIsY0FBSSxnQkFBZ0I7QUFDbEIsa0JBQU1DLG9CQUNILFFBQVEsaUJBQWlCLE1BQzFCLFFBQVEsUUFBUSwyQkFBMkIsT0FBTyxDQUFDLEdBQUcsd0JBQXdCLEdBQUc7QUFBQSxjQUMvRSxRQUFRLENBQUMsQ0FBQztBQUFBLGNBQ1YsU0FBUyxDQUFDLFdBQVcsV0FBVyxLQUFLLEVBQUU7QUFBQSxZQUN6QyxDQUFDLEVBQUUsQ0FBQztBQUNOLGdCQUFJLFdBQVcsWUFBWSxDQUFDLFFBQVEsaUJBQWlCLElBQUk7QUFDdkQsc0JBQVEsaUJBQWlCLEtBQUtBO0FBQUEsWUFDaEM7QUFDQSxnQkFBSSxVQUFVO0FBQ1osb0JBQU0sWUFBWSxjQUFjLGFBQWE7QUFDN0MsMEJBQVksT0FBTyxDQUFDLEVBQUUsUUFBUSxDQUFDLEdBQUcsT0FBTyxTQUFTLENBQUM7QUFDbkQsMEJBQVlBLGtCQUFpQixRQUFRLENBQUMsR0FBRyxXQUFXLFdBQVcsQ0FBQztBQUNoRSxrQ0FBb0IsQ0FBQyxHQUFHLE9BQU8sV0FBVztBQUFBLFlBQzVDLE9BQU87QUFDTCwwQkFBWSxPQUFPLENBQUMsRUFBRSxRQUFRLENBQUMsT0FBTyxjQUFjLFlBQVksYUFBYSxDQUFDO0FBQzlFLDBCQUFZQSxrQkFBaUIsUUFBUSxDQUFDLEdBQUcsZUFBZSxXQUFXLENBQUM7QUFDcEUsa0NBQW9CLENBQUMsT0FBTyxZQUFZLFVBQVUsV0FBVztBQUFBLFlBQy9EO0FBQ0EseUJBQWEsS0FBSyxTQUFTO0FBQzNCLHlCQUFhLEtBQUssU0FBUztBQUFBLFVBQzdCLE9BQU87QUFDTCx3QkFBWSxPQUFPLENBQUMsRUFBRSxRQUFRLENBQUMsT0FBTyxlQUFlLGNBQWMsVUFBVSxDQUFDO0FBQzlFLHdCQUFZLE9BQU8sQ0FBQyxFQUFFLFFBQVEsQ0FBQyxHQUFHLGFBQWEsYUFBYSxDQUFDO0FBQzdELGdDQUFvQixDQUFDLE9BQU8sYUFBYSxZQUFZLFFBQVE7QUFDN0QseUJBQWEsS0FBSyxTQUFTO0FBQzNCLHlCQUFhLEtBQUssU0FBUztBQUFBLFVBQzdCO0FBQ0EsY0FBSSxTQUFTO0FBQ1gseUJBQWEsS0FBSyxPQUFPLENBQUMsQ0FBQztBQUFBLFVBQzdCO0FBQ0EsZ0JBQU0sSUFBSSxrQkFBa0IsQ0FBQztBQUM3QixnQkFBTSxJQUFJLGFBQWEsQ0FBQyxFQUFFLEtBQUssYUFBYSxDQUFDLEVBQUUsS0FBSyxTQUFTLENBQUM7QUFFOUQsY0FBSSxJQUFJLEtBQUssSUFBSSxHQUFHO0FBQ2xCLG9CQUFRO0FBQUEsY0FDTjtBQUFBLGdCQUNFO0FBQUEsZ0JBQ0E7QUFBQSxnQkFDQTtBQUFBLGdCQUNBO0FBQUEsZ0JBQ0E7QUFBQSxnQkFDQTtBQUFBLGNBQ0Y7QUFBQSxjQUNBLEVBQUUsUUFBUSxhQUFhO0FBQUEsWUFDekI7QUFBQSxVQUNGLE9BQU87QUFDTCxvQkFBUTtBQUFBLGNBQ047QUFBQSxnQkFDRTtBQUFBLGdCQUNBO0FBQUEsZ0JBQ0E7QUFBQSxnQkFDQTtBQUFBLGdCQUNBO0FBQUEsZ0JBQ0E7QUFBQSxjQUNGO0FBQUEsY0FDQSxFQUFFLFFBQVEsYUFBYTtBQUFBLFlBQ3pCO0FBQUEsVUFDRjtBQUNBO0FBQUEsUUFDRjtBQUlBLGNBQU07QUFBQTtBQUFBLFVBQWdFO0FBQUE7QUFHdEUsY0FBTSxtQkFDSCxRQUFRLGlCQUFpQixNQUMxQixRQUFRLFFBQVEsMkJBQTJCLE9BQU8sQ0FBQyxHQUFHLHdCQUF3QixHQUFHO0FBQUEsVUFDL0UsUUFBUSxDQUFDLENBQUM7QUFBQSxVQUNWLFNBQVMsQ0FBQyxXQUFXLFdBQVcsS0FBSyxFQUFFO0FBQUEsUUFDekMsQ0FBQyxFQUFFLENBQUM7QUFDTixZQUFJLFdBQVcsWUFBWSxDQUFDLFFBQVEsaUJBQWlCLElBQUk7QUFDdkQsa0JBQVEsaUJBQWlCLEtBQUs7QUFBQSxRQUNoQztBQUdBLGNBQU0sYUFBYSxDQUFDLE9BQU8sQ0FBQyxHQUFHLGdCQUFnQjtBQUMvQyxZQUFJLFNBQVM7QUFDWCxxQkFBVyxLQUFLLE9BQU8sQ0FBQyxDQUFDO0FBQUEsUUFDM0I7QUFHQSxjQUFNLFlBQVksaUJBQWlCLFlBQVksV0FBVztBQUMxRCxjQUFNLFlBQVksaUJBQWlCLGNBQWMsWUFBWTtBQUM3RCxjQUFNLFdBQVcsZUFBZSxjQUFjO0FBQzlDLGdCQUFRO0FBQUEsVUFDTjtBQUFBLFlBQ0U7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFVBQ0Y7QUFBQSxVQUNBLEVBQUUsUUFBUSxXQUFXO0FBQUEsUUFDdkI7QUFBQSxNQUNGO0FBRUEsTUFBTSxTQUFTLENBQUMsU0FBeUIsZUFBcUM7QUFFNUUsY0FBTSxnQkFBZ0IsV0FBVyxXQUFXO0FBQzVDLGNBQU0sU0FBUztBQUFBLFVBQ2IsUUFBUSxPQUFPLENBQUMsRUFBRTtBQUFBLFlBQ2hCO0FBQUE7QUFBQSxjQUVJLENBQUMsUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRyxHQUFHLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUFBO0FBQUE7QUFBQSxjQUVuRixDQUFDLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRyxHQUFHLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFBQTtBQUFBLFVBQ3pGO0FBQUE7QUFBQSxVQUVBLFFBQVEsT0FBTyxDQUFDLEVBQUUsUUFBUSxDQUFDLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRyxHQUFHLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUFBLFFBQ2hIO0FBQ0EsWUFBSSxRQUFRLE9BQU8sV0FBVyxHQUFHO0FBQy9CLGlCQUFPLEtBQUssUUFBUSxPQUFPLENBQUMsQ0FBQztBQUFBLFFBQy9CO0FBQ0EsY0FBTSxPQUFPLENBQUMsR0FBRyxXQUFXLEtBQUssQ0FBQyxHQUFHLEdBQUcsV0FBVyxLQUFLLENBQUMsQ0FBQztBQUMxRCxjQUFNLFVBQVUsQ0FBQyxDQUFDLEVBQUUsT0FBTyxXQUFXLE9BQU87QUFDN0MsY0FBTSxZQUFZLENBQUMsQ0FBQyxFQUFFLE9BQU8sV0FBVyxTQUFTO0FBQ2pELGNBQU0sY0FBYyxDQUFDLENBQUMsRUFBRSxPQUFPLFdBQVcsV0FBVztBQUNyRCxjQUFNLHFCQUFxQjtBQUFBLFVBQ3pCLEVBQUUsR0FBRyxZQUFZLE1BQU0sU0FBUyxXQUFXLFlBQVk7QUFBQSxVQUN2RDtBQUFBLFFBQ0Y7QUFDQTtBQUFBLFVBQU87QUFBQSxVQUFTO0FBQUEsVUFBUTtBQUFBLFVBQW9CLENBQUMsZ0JBQzNDLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxHQUFHLFlBQVksQ0FBQyxHQUFHLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxZQUFZLENBQUMsR0FBRyxZQUFZLENBQUMsQ0FBQztBQUFBLFFBQ3BIO0FBQUEsTUFDRjtBQUVBLE1BQU0sU0FBUyxDQUFDLFNBQXlCLFFBQStCLGVBQXFDO0FBQzNHLGNBQU0sU0FBUyxXQUFXLFdBQVcsU0FBUyxpQkFBaUI7QUFDL0QsY0FBTSxxQkFBcUIsMEJBQTBCLFlBQVksTUFBTTtBQUN2RSxjQUFNLE9BQU8sV0FBVyxZQUFZLFdBQVcsV0FBVyxPQUFPLFdBQVc7QUFDNUUsY0FBTSxXQUFXO0FBQUEsVUFDZixPQUFPLENBQUMsRUFBRTtBQUFBLFVBQ1YsT0FBTyxDQUFDLEVBQUU7QUFBQSxVQUNWLFdBQVc7QUFBQSxVQUNYLFdBQVc7QUFBQSxVQUNYO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQ0EsZ0JBQVE7QUFBQSxVQUNOO0FBQUEsWUFDRTtBQUFBLFlBQ0E7QUFBQSxZQUNBLFNBQVM7QUFBQSxZQUNULENBQUMsU0FBUyxhQUFhLFNBQVMsY0FBYyxTQUFTLFdBQVc7QUFBQSxZQUNsRSxDQUFDLFNBQVMsUUFBUSxPQUFPLFNBQVMsUUFBUSxLQUFLLFNBQVMsUUFBUSxJQUFJO0FBQUEsWUFDcEU7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLE9BQU8sQ0FBQyxTQUF5QixlQUFxQztBQUNqRixRQUFBRixnQkFBZSxRQUFRLFFBQVEsVUFBVTtBQUN6QyxZQUFJLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLEdBQUc7QUFDdkMsaUJBQU8sU0FBUyxVQUFVO0FBQUEsUUFDNUIsV0FBVyxRQUFRLE9BQU8sQ0FBQyxFQUFFLEtBQUssV0FBVyxHQUFHO0FBQzlDLGlCQUFPLFNBQVMsUUFBUSxRQUFRLFVBQVU7QUFBQSxRQUM1QyxPQUFPO0FBQ0wsZ0JBQU0scUJBQXFCLDBCQUEwQixZQUFZLFFBQVEsTUFBTTtBQUMvRSxpQkFBTyxTQUFTLFFBQVEsUUFBUSxrQkFBa0I7QUFBQSxRQUNwRDtBQUFBLE1BQ0Y7QUFBQTtBQUFBOzs7QUNwYUEsTUFtQ2E7QUFuQ2I7QUFBQTtBQUFBO0FBbUJBO0FBQ0E7QUFFQTtBQUVBO0FBV08sTUFBTSxtQ0FBbUMsQ0FDOUMsUUFDQSxZQUNBLCtCQUNnQjtBQUNoQixjQUFNLFVBQVUsT0FBTyxTQUFTO0FBQ2hDLGNBQU0sY0FBYyxXQUFXO0FBQy9CLGNBQU0saUJBQWlCLFdBQVcsV0FBVztBQUM3QyxjQUFNLFFBQVEsV0FBVztBQUN6QixjQUFNLFNBQVMsT0FBTyxDQUFDLEVBQUU7QUFDekIsY0FBTSx3QkFBd0IsT0FBTyxDQUFDLElBQUk7QUFDMUMsY0FBTSx5QkFBeUIsT0FBTyxDQUFDO0FBQ3ZDLGNBQU0sY0FBYyxpQkFBaUIsaUJBQWlCLHFCQUFxQixJQUFJO0FBQy9FLGNBQU0sZUFBZSxrQkFBa0IsMkJBQTJCLEtBQUsseUJBQXlCO0FBQ2hHLGNBQU0sMkJBQTJCLGVBQzdCLEtBQUssTUFBTSx3QkFBd0IsQ0FBQyxJQUFJLElBQ3hDLEtBQUssTUFBTSx3QkFBd0IsV0FBVyxJQUFJO0FBQ3RELGNBQU0seUJBQXlCLHdCQUF3QjtBQUN2RCxjQUFNLGFBQWEsaUJBQWlCLGlCQUFpQixzQkFBc0IsSUFBSTtBQUMvRSxjQUFNLGNBQWMsaUJBQWtCLDJCQUEyQixJQUFJLGNBQWMsYUFBYztBQUNqRyxjQUFNLGFBQWEsVUFBVSxLQUFLLFdBQVcsSUFBSTtBQUNqRCxjQUFNLFdBQVcsQ0FBQyxLQUFLLEtBQUssYUFBYSxFQUFFLEdBQUcsR0FBRyxDQUFDO0FBQ2xELGtCQUFVLFdBQVcsTUFBTSx1Q0FBdUMsUUFBUSxFQUFFO0FBRTVFLGNBQU0sb0JBQXdELENBQUMsUUFBUSxNQUFNO0FBQzdFLGNBQU0sVUFBVSxDQUFDLFdBQVcsUUFBUSxDQUFDLEdBQUcsV0FBVyxRQUFRLENBQUMsQ0FBQztBQUM3RCxjQUFNLGFBQWEsQ0FBQyxXQUFXLFlBQVksaUJBQWlCLElBQUksQ0FBQyxHQUFHLFdBQVcsWUFBWSxpQkFBaUIsSUFBSSxDQUFDLENBQUM7QUFDbEgsY0FBTSxZQUFZLENBQUMsV0FBVyxVQUFVLENBQUMsR0FBRyxXQUFXLFVBQVUsQ0FBQyxDQUFDO0FBQ25FLGNBQU0sc0JBQXNCO0FBQUEsVUFDMUIsV0FBVyxDQUFDLEtBQ1QsV0FBVyxVQUFVLENBQUMsS0FBSyxJQUN4QixLQUNDLFdBQVcsWUFBWSxpQkFBaUIsSUFBSSxDQUFDLElBQUksTUFBTSxXQUFXLFVBQVUsQ0FBQyxJQUFJO0FBQUEsVUFDeEYsV0FBVyxDQUFDLEtBQ1QsV0FBVyxVQUFVLENBQUMsS0FBSyxJQUN4QixLQUNDLFdBQVcsWUFBWSxpQkFBaUIsSUFBSSxDQUFDLElBQUksTUFBTSxXQUFXLFVBQVUsQ0FBQyxJQUFJO0FBQUEsUUFDMUY7QUFDQSxjQUFNLE9BQU87QUFBQSxVQUNYLG9CQUFvQixDQUFDLElBQUksSUFBSSxLQUFLLE9BQU8sV0FBVyxLQUFLLENBQUMsSUFBSSxXQUFXLEtBQUssQ0FBQyxLQUFLLENBQUM7QUFBQSxVQUNyRixvQkFBb0IsQ0FBQyxJQUFJLElBQUksS0FBSyxPQUFPLFdBQVcsS0FBSyxDQUFDLElBQUksV0FBVyxLQUFLLENBQUMsS0FBSyxDQUFDO0FBQUEsUUFDdkY7QUFFQSxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sUUFBUTtBQUFBLFVBQ3ZDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sVUFBVTtBQUFBLFVBQ3pDLEVBQUUsdUJBQXVCLE1BQU0sb0JBQW9CO0FBQUEsVUFDbkQsRUFBRSxxQkFBc0IsTUFBTSxLQUFLO0FBQUEsVUFDbkMsRUFBRSx1QkFBdUIsTUFBTSx5QkFBeUI7QUFBQSxVQUN4RCxFQUFFLHVCQUF1QixNQUFNLHNCQUFzQjtBQUFBLFVBQ3JELEVBQUUsdUJBQXVCLE1BQU0sdUJBQXVCO0FBQUEsVUFDdEQsR0FBRywyQkFBMkIsT0FBTyxDQUFDLEVBQUUsTUFBTSxPQUFPLENBQUMsRUFBRSxJQUFJO0FBQUEsUUFDOUQ7QUFDQSxZQUFJLFNBQVM7QUFDWCwwQkFBZ0IsS0FBSyxHQUFHLDJCQUEyQixPQUFPLENBQUMsRUFBRSxJQUFJLENBQUM7QUFDbEUsNEJBQWtCLEtBQUssTUFBTTtBQUFBLFFBQy9CO0FBQ0Esd0JBQWdCLEtBQUssR0FBRywyQkFBMkIsV0FBVyxDQUFDO0FBRS9ELGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQ3RELGdCQUFNLFdBQThCO0FBQUEsWUFDbEMsRUFBRSxNQUFNLGVBQWUsTUFBTSxNQUFNO0FBQUEsWUFDbkMsRUFBRSxNQUFNLFdBQVcsTUFBTSxPQUFPLFFBQVEsUUFBUSxPQUFPO0FBQUEsWUFDdkQsRUFBRSxNQUFNLGVBQWUsTUFBTSxPQUFPLFFBQVEsV0FBVyxPQUFPO0FBQUEsWUFDOUQsRUFBRSxNQUFNLGFBQWEsTUFBTSxPQUFPLFFBQVEsV0FBVyxPQUFPO0FBQUEsWUFDNUQsRUFBRSxNQUFNLHlCQUF5QixNQUFNLE9BQU8sUUFBUSxvQkFBb0IsT0FBTztBQUFBLFlBQ2pGLEVBQUUsTUFBTSxRQUFRLE1BQU0sT0FBTyxRQUFRLEtBQUssT0FBTztBQUFBLFlBQ2pELEVBQUUsTUFBTSxnQ0FBZ0MsTUFBTSxNQUFNO0FBQUEsWUFDcEQsRUFBRSxNQUFNLDRCQUE0QixNQUFNLE1BQU07QUFBQSxZQUNoRCxFQUFFLE1BQU0sNkJBQTZCLE1BQU0sTUFBTTtBQUFBLFVBQ25EO0FBQ0EsZ0JBQU0sV0FBVyw0QkFBNEIsT0FBTyxDQUFDLEVBQUUsUUFBUTtBQUMvRCxnQkFBTSxTQUFTLGlCQUFpQixJQUFJO0FBQ3BDLGdCQUFNLFNBQVMsaUJBQWlCLElBQUk7QUFDcEMsZ0JBQU0sYUFBYSxpQkFBaUIsSUFBSTtBQUV4QyxnQkFBTSxJQUFJLGNBQWMsS0FBSyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLEtBQUssUUFBUSxXQUFXO0FBQ25GLGdCQUFNLEtBQUssY0FBYyxNQUFNLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxDQUFDLEVBQUUsS0FBSyxRQUFRLFdBQVc7QUFDckYsZ0JBQU0saUJBQWlCLENBQUMsSUFBSSxDQUFDO0FBQzdCLGNBQUksU0FBUztBQUNYLDJCQUFlLEtBQUssY0FBYyxRQUFRLE9BQU8sQ0FBQyxFQUFFLFVBQVUsQ0FBQyxZQUFZLFVBQVUsQ0FBQyxFQUFFLFFBQVEsVUFBVSxDQUFDO0FBQUEsVUFDN0c7QUFDQSxnQkFBTSxTQUFTLGVBQWUsVUFBVSxPQUFPLENBQUMsRUFBRSxVQUFVLFlBQVksUUFBUSxVQUFVO0FBRTFGLGdCQUFNLGtCQUFrQixNQUFjO0FBQ3BDLGdCQUFJLFVBQVU7QUFDZCxnQkFBSSxjQUFjO0FBQ2hCLGtCQUFJLGdCQUFnQixHQUFHO0FBQ3JCLDJCQUFXO0FBQUEsdUJBQ0UsR0FBRyxZQUFZLFVBQVUsQ0FBQztBQUFBLHVCQUMxQixFQUFFLFlBQVksVUFBVSxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUEsY0FJeEMsV0FBVyxnQkFBZ0IsR0FBRztBQUM1QiwyQkFBVztBQUFBLHlDQUNvQixRQUFRLEtBQUssR0FBRyxZQUFZLFVBQVUsQ0FBQyxLQUFLLEdBQUcsWUFBWSxlQUFlLENBQUMsV0FBVyxRQUFRLEtBQUssRUFBRSxZQUFZLFVBQVUsQ0FBQyxLQUFLLEVBQUUsWUFBWSxlQUFlLENBQUM7QUFBQTtBQUFBO0FBQUEsY0FHaE0sV0FBVyxnQkFBZ0IsR0FBRztBQUM1QiwyQkFBVztBQUFBLHlDQUNvQixRQUFRLEtBQUssR0FBRyxZQUFZLFVBQVUsQ0FBQyxLQUFLLEdBQUcsWUFBWSxlQUFlLENBQUMsS0FBSyxHQUFHLFlBQVksZUFBZSxDQUFDLEtBQUssR0FBRyxZQUFZLGVBQWUsQ0FBQyxXQUFXLFFBQVEsS0FBSyxFQUFFLFlBQVksVUFBVSxDQUFDLEtBQUssRUFBRSxZQUFZLGVBQWUsQ0FBQyxLQUFLLEVBQUUsWUFBWSxlQUFlLENBQUMsS0FBSyxFQUFFLFlBQVksZUFBZSxDQUFDO0FBQUE7QUFBQTtBQUFBLGNBRzlVO0FBQUEsWUFDRixPQUFPO0FBQ0wseUJBQVc7QUFBQSxpQ0FFQyxpQkFDSSxHQUFHO0FBQUEsZ0JBQ0QsR0FBRyxHQUFHLGdCQUFnQixHQUFHLEdBQUcsS0FBSyxPQUFPLG1DQUFtQyxDQUFDLE1BQU0sV0FBVztBQUFBLGNBQy9GLElBQ0EsR0FBRyxJQUFJLFNBQVMsZ0JBQWdCLFFBQVEsTUFBTSxDQUNwRDtBQUFBO0FBRVYsa0JBQUksZ0JBQWdCLEdBQUc7QUFDckIsMkJBQVc7QUFBQSwyQkFDTSxFQUFFLGdCQUFnQixHQUFHLEVBQUUsS0FBSyxPQUFPLHVEQUF1RCxDQUFDO0FBQUEseUJBQzdGLEVBQUUsWUFBWSxjQUFjLFdBQVcsRUFBRSxDQUFDO0FBQUE7QUFBQSxjQUUzRCxPQUFPO0FBQ0wseUJBQVMsSUFBSSxHQUFHLElBQUksYUFBYSxLQUFLO0FBQ3BDLDZCQUFXO0FBQUEsd0JBQ0MsQ0FBQyxNQUFNLEVBQUUsWUFBWSxHQUFHLEVBQUUsZ0JBQWdCLEdBQUcsRUFBRSxLQUFLLE9BQU8sNkNBQTZDLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxXQUFXLEVBQUUsQ0FBQztBQUFBLHlDQUM3SCxDQUFDLGFBQWEsQ0FBQztBQUFBLGdCQUM5QztBQUFBLGNBQ0Y7QUFBQSxZQUNGO0FBQ0EsbUJBQU87QUFBQSxVQUNUO0FBQ0EsZ0JBQU0scUJBQXFCLE1BQWM7QUFDdkMsZ0JBQUksMkJBQTJCLEdBQUc7QUFDaEMscUJBQU87QUFBQSxZQUNUO0FBQ0EsZ0JBQUksQ0FBQyxjQUFjO0FBQ2pCLG9CQUFNLElBQUksTUFBTSxnQkFBZ0IsWUFBWSxlQUFlO0FBQUEsWUFDN0Q7QUFDQSxnQkFBSSxVQUFVO0FBQ2QsZ0JBQUksZ0JBQWdCLEdBQUc7QUFDckIseUJBQVc7QUFDWCx1QkFBUyxJQUFJLEdBQUcsSUFBSSx3QkFBd0IsS0FBSztBQUMvQywyQkFBVztBQUFBLGdCQUNMLEdBQUcsWUFBWSxjQUFjLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxZQUFZLGNBQWMsQ0FBQyxFQUFFLENBQUM7QUFBQSxjQUMvRTtBQUNBLHlCQUFXO0FBQUEsWUFDYixXQUFXLGdCQUFnQixHQUFHO0FBQzVCLGtCQUFJLDJCQUEyQixHQUFHO0FBQ2hDLHNCQUFNLElBQUksTUFBTSxrQ0FBa0Msc0JBQXNCLEdBQUc7QUFBQSxjQUM3RTtBQUNBLHlCQUFXO0FBQUEseUJBQ00sR0FBRyxZQUFZLFVBQVUsQ0FBQztBQUFBLHlCQUMxQixFQUFFLFlBQVksVUFBVSxDQUFDO0FBQUE7QUFBQSxZQUU1QztBQUNBLG1CQUFPO0FBQUEsVUFDVDtBQUNBLGdCQUFNLGNBQWM7QUFBQSxrQ0FDVSxPQUFPLGdCQUFnQixnQkFBZ0IsVUFBVSxFQUFFLENBQUM7QUFBQSwwQkFDNUQsT0FBTyxXQUFXLGlCQUFpQixDQUFDLENBQUM7QUFBQSx1QkFDeEMsT0FBTyxXQUFXLGlCQUFpQixVQUFVLENBQUM7QUFBQSxzQkFDL0MsT0FBTyxXQUFXLGlCQUFpQixNQUFNLENBQUM7QUFBQSxzQkFDMUMsT0FBTyxXQUFXLGlCQUFpQixNQUFNLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLDRCQVFwQyxPQUFPLEtBQUssS0FBSztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLDJCQVVsQixRQUFRLGlCQUFpQixRQUFRLFdBQVcsUUFBUTtBQUFBO0FBQUEsd0NBRXZDLFFBQVEsc0JBQXNCLE1BQU07QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLDZCQWMvQyxRQUFRLGlCQUFpQixRQUFRLFdBQVcsUUFBUTtBQUFBO0FBQUEsMENBRXZDLFFBQVEsc0JBQXNCLE1BQU07QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0JBTzVELGVBQ0k7QUFBQSxpQ0FDVyxHQUFHLGdCQUFnQixHQUFHLEdBQUcsS0FBSyxPQUFPLG1DQUFtQyxDQUFDLE1BQU0sV0FBVztBQUFBLGlDQUMxRixFQUFFLGdCQUFnQixHQUFHLEVBQUUsS0FBSyxPQUFPLDZDQUE2QyxDQUFDLE1BQU0sV0FBVztBQUFBLHNCQUU3RyxFQUNOO0FBQUEsOEZBQzhFLGVBQWUsSUFBSSxXQUFXO0FBQUEsb0JBQ3hHLGdCQUFnQixDQUFDO0FBQUEsa0RBQ2EsZUFBZSxJQUFJLFdBQVc7QUFBQTtBQUFBLGtCQUU5RCxtQkFBbUIsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsaUNBS0wsVUFBVSxnQkFBZ0IsVUFBVSxNQUFNLEVBQUU7QUFBQSxjQUMvRCxPQUFPLFlBQVksY0FBYyxPQUFPLENBQUM7QUFBQTtBQUduRCxpQkFBTztBQUFBLE1BQ0wsYUFBYSxpQkFBaUIsUUFBUSxFQUFFLGlCQUFpQixHQUFHLGdCQUFnQixNQUFNLENBQUM7QUFBQSxRQUNqRixhQUFhLFVBQVUsQ0FBQztBQUFBLFFBQ3hCLGFBQWEsc0NBQXNDLHNCQUFzQixDQUFDO0FBQUEsTUFDNUUsV0FBVztBQUFBLFFBQ2Y7QUFFQSxlQUFPO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixhQUFhO0FBQUEsWUFDWCxNQUFNLEdBQUcsV0FBVyxRQUFRLElBQUksV0FBVyxHQUFHLFdBQVcsR0FBRyxVQUFVLEdBQUcsWUFBWSxHQUFHLHNCQUFzQjtBQUFBLFlBQzlHO0FBQUEsVUFDRjtBQUFBLFVBQ0EsWUFBWSxPQUFPO0FBQUEsWUFDakIsZUFBZSxFQUFFLEdBQUcsU0FBUyxDQUFDLEdBQUcsR0FBRyxTQUFTLENBQUMsR0FBRyxHQUFHLFNBQVMsQ0FBQyxFQUFFO0FBQUEsWUFDaEUsU0FBUztBQUFBLGNBQ1A7QUFBQSxnQkFDRSxNQUFNLDZCQUE2QiwyQkFBMkIsV0FBVyxJQUFJO0FBQUEsZ0JBQzdFLFVBQVUsT0FBTyxDQUFDLEVBQUU7QUFBQSxjQUN0QjtBQUFBLFlBQ0Y7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQzlSQSxNQVdNLGlCQVNBLG1CQVdBLDZCQTRDQSxvQ0FtRE8sOEJBK0JQRyxpQkF1RUEsaUJBMkJBLGlCQWtETztBQWpUYjtBQUFBO0FBQUE7QUFNQTtBQUVBO0FBQ0E7QUFFQSxNQUFNLGtCQUFrQixDQUN0QixPQUNBLFFBQ0EsS0FDQSxRQUNBLFVBQ0EsYUFDSSxRQUFRLEtBQUssU0FBUyxPQUFPLFNBQVMsS0FBSyxXQUFXLElBQUk7QUFFaEUsTUFBTSxvQkFBb0IsQ0FBQyxVQUFrQixTQUFpQixNQUFnQixNQUFjLFNBQWlCO0FBQzNHLGNBQU0sV0FBVyxLQUFLLE1BQU0sV0FBVyxDQUFDO0FBQ3hDLFlBQUksWUFBWSxjQUFjO0FBQzVCLGVBQUssSUFBSSxJQUFJO0FBQ2IsZUFBSyxJQUFJLElBQUksV0FBVztBQUFBLFFBQzFCLFdBQVcsWUFBWSxjQUFjO0FBQ25DLGVBQUssSUFBSSxJQUFJLFdBQVc7QUFDeEIsZUFBSyxJQUFJLElBQUk7QUFBQSxRQUNmO0FBQUEsTUFDRjtBQUVBLE1BQU0sOEJBQThCLENBQ2xDLFlBQ0EsYUFDQSxXQUNBLFNBQ0EsT0FDQSxNQUNBLFNBQ0EsZUFDQSxlQUNBLGdCQUNHO0FBQ0gsY0FBTSxjQUFjLFdBQVcsU0FBUztBQUN4QyxjQUFNLG9CQUFvQixZQUFZLFdBQVc7QUFDakQsWUFBSSxjQUFjLFNBQVMsYUFBYTtBQUN0Qyx3QkFBYyxLQUFLLEdBQUcsTUFBTSxjQUFjLGNBQWMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQUEsUUFDekU7QUFDQSxjQUFNLFlBQVksV0FBVyxDQUFDO0FBQzlCLGNBQU0sY0FBYyxZQUFZLGdCQUFnQixJQUFJLENBQUMsSUFBSTtBQUN6RCxpQkFBUyxJQUFJLEdBQUcsSUFBSSxXQUFXLFNBQVMsZUFBZSxnQkFBZ0IsSUFBSSxJQUFJLElBQUksYUFBYSxFQUFFLEdBQUcsRUFBRSxHQUFHO0FBQ3hHLGdCQUFNLFNBQVMsV0FBVyxDQUFDO0FBQzNCLGdCQUFNLFVBQVUsb0JBQW9CLFNBQVMsUUFBUSxDQUFDLElBQUksWUFBWSxDQUFDO0FBQ3ZFLGdCQUFNLFdBQVcsZ0JBQWdCLFFBQVEsUUFBUSxDQUFDLEdBQUcsS0FBSyxDQUFDLEdBQUcsWUFBWSxDQUFDLEdBQUcsVUFBVSxDQUFDLEdBQUcsT0FBTztBQUNuRyw0QkFBa0IsVUFBVSxTQUFTLE1BQU0sR0FBRyxJQUFJLFdBQVc7QUFDN0QsY0FBSSxtQkFBbUI7QUFDckIsd0JBQVk7QUFBQSxjQUNWLFFBQVEsQ0FBQyxLQUFLLFNBQVMsS0FDckIsY0FBYyxDQUFDLEtBQ2QsWUFBWSxDQUFDLElBQUksS0FBSyxVQUFVLENBQUMsSUFDbEMsSUFDQSxLQUFLLENBQUMsSUFDTixLQUFLLElBQUksV0FBVztBQUFBLFlBQ3hCO0FBQUEsVUFDRjtBQUFBLFFBQ0Y7QUFDQSxvQkFBWSxPQUFPLEdBQUcsR0FBRyxTQUFTO0FBQ2xDLG9CQUFZLE9BQU8sZ0JBQWdCLElBQUksR0FBRyxHQUFHLFdBQVc7QUFBQSxNQUMxRDtBQU9BLE1BQU0scUNBQXFDLENBQ3pDLFlBQ0EsV0FDTTtBQUNOLGNBQU0sY0FBYyxXQUFXLFlBQVksTUFBTTtBQUVqRCxZQUFJLFdBQVcsWUFBWSxXQUFXLEtBQUssV0FBVyxZQUFZLE9BQU8sQ0FBQyxHQUFHLE1BQU0sSUFBSSxHQUFHLENBQUMsTUFBTSxHQUFHO0FBQ2xHLHNCQUFZLFNBQVM7QUFDckIsbUJBQVMsSUFBSSxHQUFHLElBQUksT0FBTyxDQUFDLEVBQUUsS0FBSyxRQUFRLEVBQUUsR0FBRztBQUM5Qyx3QkFBWSxLQUFLLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQUEsVUFDcEM7QUFBQSxRQUNGO0FBQ0EsY0FBTSxpQkFBaUIsV0FBVyxXQUFXO0FBQzdDLG9CQUFZLE9BQU8sR0FBRyxHQUFHLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQzFDLG9CQUFZLE9BQU8saUJBQWlCLElBQUksR0FBRyxHQUFHLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBRS9ELGNBQU0sT0FBTyxXQUFXLEtBQUssTUFBTTtBQUNuQyxjQUFNLGNBQWMsV0FBVyxZQUFZLE1BQU07QUFDakQsY0FBTSxnQkFBZ0IsV0FBVyxjQUFjLE1BQU07QUFDckQsY0FBTSxhQUFhLE9BQU8sQ0FBQyxFQUFFO0FBQzdCLFlBQUksWUFBWSxXQUFXLFVBQVUsTUFBTTtBQUMzQyxZQUFJLFVBQVUsT0FBTyxDQUFDLEdBQUcsTUFBTSxJQUFJLEdBQUcsQ0FBQyxNQUFNLEdBQUc7QUFDOUMsZ0JBQU0sY0FBYyxPQUFPLENBQUMsRUFBRSxLQUFLLFNBQVM7QUFDNUMsc0JBQVksSUFBSSxNQUFNLFdBQVcsRUFBRSxLQUFLLENBQUM7QUFBQSxRQUMzQztBQUNBLFlBQUksVUFBVSxXQUFXLFFBQVEsTUFBTTtBQUN2QyxZQUFJLFFBQVEsT0FBTyxDQUFDLEdBQUcsTUFBTSxJQUFJLEdBQUcsQ0FBQyxNQUFNLEdBQUc7QUFDNUMsZ0JBQU0sY0FBYyxPQUFPLENBQUMsRUFBRSxLQUFLLFNBQVM7QUFDNUMsb0JBQVUsSUFBSSxNQUFNLFdBQVcsRUFBRSxLQUFLLENBQUM7QUFBQSxRQUN6QztBQUdBO0FBQUEsVUFDRTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQSxXQUFXO0FBQUEsVUFDWCxXQUFXO0FBQUEsVUFDWDtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBR0EsY0FBTSxnQkFBbUIsT0FBTyxPQUFPLENBQUMsR0FBRyxVQUFVO0FBQ3JELGVBQU8sT0FBTyxlQUFlLEVBQUUsYUFBYSxNQUFNLGVBQWUsYUFBYSxXQUFXLFFBQVEsQ0FBQztBQUNsRyxlQUFPO0FBQUEsTUFDVDtBQUVPLE1BQU0sK0JBQStCLENBQUMsZUFBaUU7QUFDNUcsY0FBTSx1QkFBdUIsa0NBQWtDLFVBQVU7QUFFekUsY0FBTSxTQUFTLFdBQVc7QUFDMUIsY0FBTSxVQUFVLENBQUMsVUFBVSxTQUFTLGNBQWMsWUFBWSxFQUM1RCxPQUFPLFdBQVcsV0FBVyxjQUFjLElBQUssV0FBVyxPQUM3RDtBQUNBLGNBQU0sWUFBWSxXQUFXO0FBQzdCLGNBQU0sUUFBUSxXQUFXO0FBQ3pCLGNBQU0sY0FBYyxXQUFXO0FBQy9CLGNBQU0sT0FBTyxXQUFXO0FBQ3hCLGNBQU0sVUFBVSxXQUFXO0FBQzNCLGNBQU0sV0FBWSxXQUFXLFNBQTJCO0FBQ3hELGNBQU0sZ0JBQWdCLFdBQVc7QUFDakMsY0FBTSxjQUFjLFdBQVc7QUFDL0IsZUFBTztBQUFBLFVBQ0w7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBLEdBQUc7QUFBQSxVQUNILFVBQVUsR0FBRyxXQUFXLE1BQU0sSUFBSSxxQkFBcUIsVUFBVTtBQUFBLFFBQ25FO0FBQUEsTUFDRjtBQUVBLE1BQU1BLGtCQUFpQixDQUFDLFFBQStCLGVBQThDO0FBR25HLFlBQUksQ0FBQyxVQUFXLE9BQU8sV0FBVyxLQUFLLE9BQU8sV0FBVyxHQUFJO0FBQzNELGdCQUFNLElBQUksTUFBTSw2QkFBNkI7QUFBQSxRQUMvQztBQUdBLFlBQUksT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLEtBQUssT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLEdBQUc7QUFDOUQsZ0JBQU0sSUFBSSxNQUFNLDJDQUEyQztBQUFBLFFBQzdEO0FBRUEsWUFBSSxPQUFPLENBQUMsRUFBRSxLQUFLLFdBQVcsT0FBTyxDQUFDLEVBQUUsS0FBSyxRQUFRO0FBQ25ELGdCQUFNLElBQUksTUFBTSw4Q0FBOEM7QUFBQSxRQUNoRTtBQUdBLGNBQU0sY0FBYyxPQUFPLENBQUMsRUFBRSxLQUFLLFdBQVcsV0FBVyxTQUFTLE9BQU8sQ0FBQyxFQUFFLEtBQUssU0FBUyxJQUFJLENBQUM7QUFDL0YsY0FBTSxrQkFBa0IsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDO0FBQ3hDLFlBQUksZ0JBQWdCLGlCQUFpQjtBQUNuQyxnQkFBTSxJQUFJLE1BQU0sbURBQW1EO0FBQUEsUUFDckU7QUFFQSxjQUFNLGNBQWMsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLElBQUksV0FBVztBQUduRCxZQUFJLE9BQU8sV0FBVyxNQUFNLE9BQU8sQ0FBQyxFQUFFLEtBQUssV0FBVyxLQUFLLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxNQUFNLGNBQWM7QUFDN0YsZ0JBQU0sSUFBSSxNQUFNLGNBQWM7QUFBQSxRQUNoQztBQUVBLGNBQU0sY0FBYyxPQUFPLENBQUMsRUFBRSxLQUFLLFNBQVM7QUFDNUMsY0FBTSxlQUFlLFdBQVcsVUFBVSxPQUFPLENBQUMsR0FBRyxNQUFNLElBQUksR0FBRyxDQUFDLElBQUk7QUFFdkUsWUFBSSxnQkFBZ0IsV0FBVyxVQUFVLFdBQVcsYUFBYTtBQUMvRCxnQkFBTSxJQUFJLE1BQU0sdUJBQXVCLFdBQVcsR0FBRztBQUFBLFFBQ3ZEO0FBRUEsY0FBTSxhQUFhLFdBQVcsUUFBUSxPQUFPLENBQUMsR0FBRyxNQUFNLElBQUksR0FBRyxDQUFDLElBQUk7QUFFbkUsWUFBSSxjQUFjLFdBQVcsUUFBUSxXQUFXLGFBQWE7QUFDM0QsZ0JBQU0sSUFBSSxNQUFNLHFCQUFxQixXQUFXLEdBQUc7QUFBQSxRQUNyRDtBQUdBLGNBQU0sVUFBVSxXQUFXLEtBQUssT0FBTyxDQUFDLEdBQUcsTUFBTSxJQUFJLEdBQUcsQ0FBQyxJQUFJO0FBQzdELFlBQUksV0FBVyxXQUFXLEtBQUssV0FBVyxjQUFjLEdBQUc7QUFDekQsZ0JBQU0sSUFBSSxNQUFNLGtCQUFrQixjQUFjLENBQUMsR0FBRztBQUFBLFFBQ3REO0FBR0EsWUFBSSxXQUFXLGNBQWMsV0FBVyxlQUFlLFdBQVcsY0FBYyxXQUFXLEdBQUc7QUFDNUYsZ0JBQU0sSUFBSSxNQUFNLDRCQUE0QixXQUFXLEdBQUc7QUFBQSxRQUM1RDtBQUlBLGNBQU0saUJBQWlCLFdBQVcsWUFBWSxPQUFPLENBQUMsR0FBRyxNQUFNLElBQUksR0FBRyxDQUFDLElBQUk7QUFDM0UsWUFDRSxrQkFDQSxXQUFXLFlBQVksV0FBVyxLQUNsQyxXQUFXLFlBQVksV0FBVyxPQUFPLENBQUMsRUFBRSxLQUFLLFNBQVMsR0FDMUQ7QUFDQSxnQkFBTSxJQUFJLE1BQU0sc0JBQXNCO0FBQUEsUUFDeEM7QUFHQSxZQUFJLFdBQVcsWUFBWSxXQUFXLEtBQUssV0FBVyxZQUFZLFdBQVcsT0FBTyxDQUFDLEVBQUUsS0FBSyxTQUFTLEdBQUc7QUFDdEcsZ0JBQU0sSUFBSSxNQUFNLHNCQUFzQjtBQUFBLFFBQ3hDO0FBQUEsTUFDRjtBQUVBLE1BQU0sa0JBQWtCLENBQ3RCLFNBQ0EsUUFDQSxZQUNBLCtCQUNTO0FBRVQsY0FBTSxtQkFDSCxRQUFRLGlCQUFpQixNQUMxQixRQUFRLFFBQVEsMkJBQTJCLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEdBQUc7QUFBQSxVQUNuRSxRQUFRLENBQUMsQ0FBQztBQUFBLFVBQ1YsU0FBUyxDQUFDLFdBQVcsV0FBVyxLQUFLLEVBQUU7QUFBQSxRQUN6QyxDQUFDLEVBQUUsQ0FBQztBQUNOLFlBQUksV0FBVyxZQUFZLENBQUMsUUFBUSxpQkFBaUIsSUFBSTtBQUN2RCxrQkFBUSxpQkFBaUIsS0FBSztBQUFBLFFBQ2hDO0FBR0EsY0FBTSxzQkFBc0IsQ0FBQyxPQUFPLENBQUMsR0FBRyxnQkFBZ0I7QUFDeEQsWUFBSSxPQUFPLFdBQVcsR0FBRztBQUN2Qiw4QkFBb0IsS0FBSyxPQUFPLENBQUMsQ0FBQztBQUFBLFFBQ3BDO0FBQ0EsZ0JBQVEsUUFBUSxpQ0FBaUMscUJBQXFCLFlBQVksMEJBQTBCLEdBQUc7QUFBQSxVQUM3RyxRQUFRO0FBQUEsUUFDVixDQUFDO0FBQUEsTUFDSDtBQUVBLE1BQU0sa0JBQWtCLENBQUMsU0FBeUIsZUFBOEM7QUFFOUYsY0FBTSxnQkFBZ0IsV0FBVyxXQUFXO0FBRTVDLGNBQU0sU0FBUztBQUFBLFVBQ2IsUUFBUSxPQUFPLENBQUMsRUFBRTtBQUFBLFlBQ2hCO0FBQUE7QUFBQSxjQUVJLENBQUMsUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRyxHQUFHLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUFBO0FBQUE7QUFBQSxjQUVuRixDQUFDLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRyxHQUFHLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFBQTtBQUFBLFVBQ3pGO0FBQUE7QUFBQSxVQUVBLFFBQVEsT0FBTyxDQUFDLEVBQUUsUUFBUSxDQUFDLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRyxHQUFHLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUFBLFFBQ2hIO0FBQ0EsWUFBSSxRQUFRLE9BQU8sV0FBVyxHQUFHO0FBQy9CLGlCQUFPLEtBQUssUUFBUSxPQUFPLENBQUMsQ0FBQztBQUFBLFFBQy9CO0FBQ0EsWUFBSSxjQUFjLFdBQVc7QUFDN0IsWUFBSSxZQUFZLFdBQVcsS0FBSyxZQUFZLENBQUMsTUFBTSxHQUFHO0FBQ3BELHdCQUFjLENBQUMsUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUFBLFFBQzFDO0FBQ0EsWUFBSSxZQUFZLFdBQVc7QUFDM0IsWUFBSSxVQUFVLFdBQVcsS0FBSyxVQUFVLENBQUMsTUFBTSxHQUFHO0FBQ2hELHNCQUFZLENBQUMsQ0FBQztBQUFBLFFBQ2hCO0FBQ0EsWUFBSSxVQUFVLFdBQVc7QUFDekIsWUFBSSxRQUFRLFdBQVcsS0FBSyxRQUFRLENBQUMsTUFBTSxHQUFHO0FBQzVDLG9CQUFVLENBQUMsQ0FBQztBQUFBLFFBQ2Q7QUFDQSxZQUFJLE9BQU8sV0FBVztBQUN0QixZQUFJLEtBQUssV0FBVyxHQUFHO0FBQ3JCLGlCQUFPLENBQUMsR0FBRyxDQUFDO0FBQUEsUUFDZDtBQUNBLGVBQU8sQ0FBQyxHQUFHLEtBQUssQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLENBQUM7QUFDOUIsa0JBQVUsQ0FBQyxDQUFDLEVBQUUsT0FBTyxPQUFPO0FBQzVCLG9CQUFZLENBQUMsQ0FBQyxFQUFFLE9BQU8sU0FBUztBQUNoQyxzQkFBYyxDQUFDLENBQUMsRUFBRSxPQUFPLFdBQVc7QUFDcEMsWUFBSSxnQkFBZ0IsV0FBVztBQUMvQix3QkFBZ0IsQ0FBQyxDQUFDLEVBQUUsT0FBTyxhQUFhO0FBQ3hDLGNBQU0scUJBQXFCO0FBQUEsVUFDekIsRUFBRSxHQUFHLFlBQVksTUFBTSxTQUFTLFdBQVcsYUFBYSxjQUFjO0FBQUEsVUFDdEU7QUFBQSxRQUNGO0FBRUE7QUFBQSxVQUFnQjtBQUFBLFVBQVM7QUFBQSxVQUFRO0FBQUEsVUFBb0IsQ0FBQyxnQkFDcEQsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLEdBQUcsWUFBWSxDQUFDLEdBQUcsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLFlBQVksQ0FBQyxHQUFHLFlBQVksQ0FBQyxDQUFDO0FBQUEsUUFDcEg7QUFBQSxNQUNGO0FBRU8sTUFBTSxnQkFBZ0IsQ0FBQyxTQUF5QixlQUE4QztBQUNuRyxRQUFBQSxnQkFBZSxRQUFRLFFBQVEsVUFBVTtBQUN6QyxZQUFJLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLEdBQUc7QUFDdkMsMEJBQWdCLFNBQVMsVUFBVTtBQUFBLFFBQ3JDLE9BQU87QUFDTCxnQkFBTSxxQkFBcUIsbUNBQW1DLFlBQVksUUFBUSxNQUFNO0FBQ3hGLDBCQUFnQixTQUFTLFFBQVEsUUFBUSxrQkFBa0I7QUFBQSxRQUM3RDtBQUFBLE1BQ0Y7QUFBQTtBQUFBOzs7QUN6VEEsTUFlTSx5QkFvRE8sUUFPQTtBQTFFYjtBQUFBO0FBQUE7QUFHQTtBQUVBO0FBQ0E7QUFHQTtBQU1BLE1BQU0sMEJBQTBCLENBQzlCLFdBQ0EsWUFDQSxXQUNBLGVBQ2dCO0FBQ2hCLGNBQU0sYUFBYSxVQUFVLEtBQUssVUFBVTtBQUM1QyxjQUFNLE9BQU8sV0FBVztBQUN4QixjQUFNLFFBQVEsY0FBYyxTQUFTLFdBQVcsSUFBSTtBQUNwRCxjQUFNLFNBQVMsZUFBZSxVQUFVLFdBQVcsSUFBSTtBQUN2RCxjQUFNLFlBQ0osVUFBVSw2QkFBOEIsVUFBVSxjQUFjLEVBQUUsQ0FBQyxJQUFJLE9BQU8sVUFBVSxpQkFBaUIsRUFBRSxDQUFDLENBQUM7QUFDL0csY0FBTSxPQUFPLFVBQVUsY0FBYyxXQUFXLElBQUk7QUFDcEQsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFDdEQsZ0JBQU0sUUFBUSxRQUFRLE1BQU0sV0FBVyxnQkFBZ0IsZUFBZSxDQUFDO0FBQ3ZFLGdCQUFNLE1BQU0sYUFBYSx3QkFBd0IsaUJBQWlCLElBQUk7QUFDdEUsZ0JBQU0sYUFBYSxXQUFXLFVBQVUsU0FBUyxXQUFXLFlBQVksU0FBUyxNQUFNO0FBQ3ZGLGdCQUFNLGFBQWEsV0FBVyxVQUFVLE1BQU0sU0FBUyxXQUFXLFlBQVksS0FBSztBQUNuRixpQkFBTztBQUFBLGtCQUNPLGFBQ0MsZ0JBQWdCLGNBQWMsS0FBSyxFQUNuQyxnQkFBZ0IsUUFBUSxLQUFLLEVBQzdCLGlCQUFpQixPQUFPLE1BQU0sQ0FBQztBQUFBLGtCQUNoQyxhQUFhLFVBQVUsQ0FBQztBQUFBLG9CQUN0QixhQUFhLHNDQUFzQyxxQkFBcUIsQ0FBQztBQUFBLHVDQUN0RCxPQUFPLGdCQUFnQixZQUFZLENBQUM7QUFBQSw4QkFDN0MsT0FBTyxLQUFLLEtBQUs7QUFBQSxzQ0FDVCxVQUFVO0FBQUEscUNBQ1gsVUFBVTtBQUFBO0FBQUEsc0JBRXpCLE1BQU0sV0FBVyxnQkFBZ0IsaUJBQWlCLFFBQVEsQ0FBQztBQUFBLGtDQUMvQyxNQUFNLGFBQWEsY0FBYyxDQUFDO0FBQUE7QUFBQSxvQkFFaEQsT0FBTyxZQUFZLGNBQWMsS0FBSyxDQUFDO0FBQUE7QUFBQSxRQUV6RDtBQUNBLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWEsRUFBRSxNQUFNLFdBQVcsVUFBVSxtQkFBbUIsQ0FBQyxNQUFNLEVBQUU7QUFBQSxVQUN0RSxZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLFlBQVksVUFBVSxVQUFVLENBQUM7QUFBQSxZQUNuRCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxhQUFhO0FBQUE7QUFBQSxZQUF1QixFQUFFO0FBQUEsWUFDcEUsaUJBQWlCO0FBQUEsY0FDZixFQUFFLHVCQUF1QixNQUFNLFdBQVc7QUFBQSxjQUMxQyxFQUFFLHVCQUF1QixNQUFNLEtBQUs7QUFBQSxjQUNwQyxHQUFHLDJCQUEyQixZQUFZLFVBQVU7QUFBQSxZQUN0RDtBQUFBLFVBQ0Y7QUFBQSxVQUNBO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLFNBQVMsQ0FBQyxTQUF5QixlQUF1QztBQUNyRixjQUFNLGFBQWEsUUFBUSxPQUFPLENBQUMsRUFBRTtBQUNyQyxjQUFNLFlBQVksUUFBUSxPQUFPLENBQUMsRUFBRTtBQUNwQyxjQUFNLE9BQU8sUUFBUSxPQUFPLENBQUM7QUFDN0IsZ0JBQVEsUUFBUSx3QkFBd0IsV0FBVyxZQUFZLE1BQU0sVUFBVSxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDO0FBQUEsTUFDbkc7QUFFTyxNQUFNLHdCQUF3QixDQUFDLGVBQTBEO0FBQzlGLGNBQU0sWUFBYSxXQUFXLGNBQXlCO0FBQ3ZELGNBQU0sVUFBVyxXQUFXLFlBQXVCO0FBQ25ELGVBQU8sNEJBQTRCLEVBQUUsV0FBVyxRQUFRLENBQUM7QUFBQSxNQUMzRDtBQUFBO0FBQUE7OztBQzlFQSxNQW9CTUMsa0JBU0FDLG1CQVdBLCtCQW1FTyxjQUtBO0FBaEhiO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFDQTtBQUdBO0FBV0EsTUFBTUQsbUJBQWlCLENBQUMsV0FBd0M7QUFDOUQsWUFBSSxDQUFDLFVBQVUsT0FBTyxXQUFXLEdBQUc7QUFDbEMsZ0JBQU0sSUFBSSxNQUFNLGdDQUFnQztBQUFBLFFBQ2xEO0FBQ0EsWUFBSSxPQUFPLENBQUMsRUFBRSxLQUFLLFdBQVcsR0FBRztBQUMvQixnQkFBTSxJQUFJLE1BQU0saUNBQWlDO0FBQUEsUUFDbkQ7QUFBQSxNQUNGO0FBRUEsTUFBTUMsb0JBQW1CLENBQUMsTUFBZ0IsTUFBYyxPQUFzQixXQUFrQztBQUM5RyxjQUFNLGNBQWMsQ0FBQztBQUNyQixvQkFBWSxLQUFLLGNBQWMsT0FBTyxLQUFLLE9BQU8sUUFBUSxNQUFNLEtBQUssT0FBTztBQUFBLGFBQ2pFLE1BQU0sS0FBSyxPQUFPLEdBQUc7QUFDaEMsaUJBQVMsSUFBSSxHQUFHLElBQUksTUFBTSxFQUFFLEdBQUc7QUFDN0Isc0JBQVksS0FBSyxNQUFNLFdBQVcsS0FBSyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDO0FBQUEsUUFDNUQ7QUFDQSxvQkFBWSxLQUFLLFlBQVk7QUFDN0IsZUFBTyxZQUFZLEtBQUssSUFBSTtBQUFBLE1BQzlCO0FBRUEsTUFBTSxnQ0FBZ0MsQ0FBQyxhQUF5QixlQUFvRDtBQUNsSCxZQUFJLEdBQVcsR0FBVyxHQUFXO0FBQ3JDLFlBQUk7QUFDSixZQUFJO0FBQ0osY0FBTSxnQkFBZ0IsV0FBVyxXQUFXO0FBQzVDLGNBQU0sWUFBWSxXQUFXO0FBQzdCLGNBQU0sWUFBWSxXQUFXLFNBQVM7QUFDdEMsWUFBSSxlQUFlO0FBQ2pCLFdBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxJQUFJLFlBQVk7QUFDM0Isa0JBQVEsWUFDSixDQUFDLEdBQUcsR0FBRyxHQUFHLFdBQVcsV0FBVyxJQUFJLGFBQWEsQ0FBQyxJQUNsRCxDQUFDLEdBQUcsR0FBRyxHQUFHLElBQUksYUFBYSxHQUFHLFdBQVcsU0FBUztBQUN0RCxpQkFBTyxZQUFZLENBQUMsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxDQUFDO0FBQUEsUUFDM0QsT0FBTztBQUNMLFdBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxLQUFLLENBQUMsR0FBRyxZQUFZLEtBQUssQ0FBQyxHQUFHLFlBQVksS0FBSyxDQUFDLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQztBQUNsRyxrQkFBUSxZQUNKLENBQUMsR0FBRyxXQUFXLFdBQVcsSUFBSSxhQUFhLEdBQUcsR0FBRyxDQUFDLElBQ2xELENBQUMsR0FBRyxJQUFJLGFBQWEsR0FBRyxXQUFXLFdBQVcsR0FBRyxDQUFDO0FBQ3RELGlCQUFPLFlBQVksQ0FBQyxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLENBQUM7QUFBQSxRQUMzRDtBQUNBLGNBQU0sc0JBQXNCLFlBQVksUUFBUSxLQUFLO0FBQ3JELGNBQU0sb0JBQW9CLG9CQUFvQixLQUFLO0FBQ25ELGNBQU0sZ0JBQWdCLFlBQVk7QUFFbEMsY0FBTSxnQkFBZ0IsY0FBYyxLQUFLLGVBQWUsaUJBQWlCO0FBQ3pFLGNBQU0sZUFBZSxlQUFlLFVBQVUsZUFBZSxpQkFBaUI7QUFFOUUsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFBQSxJQUN0RCxhQUFhLGdCQUFnQixlQUFlLEtBQUssRUFBRSxpQkFBaUIsZUFBZSxZQUFZLENBQUM7QUFBQTtBQUFBLElBRWhHQSxrQkFBaUIsTUFBTSxtQkFBbUIsZUFBZSxZQUFZLENBQUM7QUFBQTtBQUFBLElBRXRFLGFBQWEsVUFBVSxDQUFDO0FBQUEsTUFDdEIsYUFBYSxzQ0FBc0Msc0JBQXNCLENBQUM7QUFBQTtBQUFBLG9CQUU1RCxhQUFhLGdCQUFnQixZQUFZLENBQUM7QUFBQTtBQUFBO0FBQUEsTUFHeEQsYUFBYSxZQUFZLGNBQWMsY0FBYyxhQUFhLFVBQVUsQ0FBQyxDQUFDO0FBQUE7QUFHbEYsZUFBTztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sYUFBYTtBQUFBLFlBQ1gsTUFBTSxHQUFHLFlBQVksSUFBSSxJQUFJLFdBQVcsU0FBUyxJQUFJLFdBQVcsSUFBSTtBQUFBLFlBQ3BFLG1CQUFtQixDQUFDLE1BQU07QUFBQSxVQUM1QjtBQUFBLFVBQ0EsWUFBWSxDQUFDLFdBQVc7QUFDdEIsa0JBQU0sY0FBYyxnQkFDaEIsQ0FBQyxHQUFHLElBQUksV0FBVyxJQUFJLFdBQVcsSUFBSSxhQUFhLENBQUMsSUFDcEQsQ0FBQyxHQUFHLElBQUksYUFBYSxHQUFHLElBQUksV0FBVyxJQUFJLFNBQVM7QUFDeEQsa0JBQU0sYUFBYSxVQUFVLEtBQUssV0FBVztBQUM3QyxrQkFBTSxrQkFBa0Isb0JBQW9CO0FBQzVDLGtCQUFNLGlCQUFpQixVQUFVLGdCQUFnQixpQkFBaUIsSUFBSTtBQUN0RSxtQkFBTztBQUFBLGNBQ0wsU0FBUyxDQUFDLEVBQUUsTUFBTSxhQUFhLFVBQVUsT0FBTyxDQUFDLEVBQUUsU0FBUyxDQUFDO0FBQUEsY0FDN0QsZUFBZSxFQUFFLEdBQUcsS0FBSztBQUFBLGdCQUFLLGFBQWE7QUFBQTtBQUFBLGNBQXVCLEVBQUU7QUFBQSxjQUNwRSxpQkFBaUI7QUFBQSxnQkFDZixFQUFFLHVCQUF1QixNQUFNLFdBQVc7QUFBQSxnQkFDMUMsR0FBRywyQkFBMkIsaUJBQWlCLGNBQWM7QUFBQSxjQUMvRDtBQUFBLFlBQ0Y7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxlQUFlLENBQUMsU0FBeUIsZUFBNkM7QUFDakcsUUFBQUQsaUJBQWUsUUFBUSxNQUFNO0FBQzdCLGdCQUFRLFFBQVEsOEJBQThCLFFBQVEsT0FBTyxDQUFDLEdBQUcsVUFBVSxDQUFDO0FBQUEsTUFDOUU7QUFFTyxNQUFNLDhCQUE4QixDQUFDLGVBQzFDLDRCQUE0QjtBQUFBLFFBQzFCLFdBQVcsV0FBVztBQUFBLFFBQ3RCLE1BQU0sV0FBVztBQUFBLFFBQ2pCLFFBQVEsV0FBVztBQUFBLE1BQ3JCLENBQUM7QUFBQTtBQUFBOzs7QUNySEgsTUFzQk0sZUFDQSxhQUNBLGlCQUNBLFlBQ0EsZ0JBUUEsWUFxQkEsZ0JBaUlBLFdBRUEseUJBcUhPLFFBT0E7QUF0VGI7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUNBO0FBR0E7QUFhQSxNQUFNLGdCQUFnQjtBQUN0QixNQUFNLGNBQWMsTUFBTSxnQkFBZ0I7QUFDMUMsTUFBTSxrQkFBa0IsTUFBTSxjQUFjO0FBQzVDLE1BQU0sYUFBYSxNQUFNLGNBQWMsUUFBUTtBQUMvQyxNQUFNLGlCQUFpQixNQUFNLGFBQWE7QUFRMUMsTUFBTSxhQUFOLE1BQWlCO0FBQUEsUUFDZixZQUFZLGFBQWEsSUFBSTtBQUMzQixlQUFLLGtCQUFrQixvQkFBSSxJQUFzQjtBQUNqRCxlQUFLLGFBQWE7QUFBQSxRQUNwQjtBQUFBO0FBQUEsUUFHQSxVQUFVLFFBQWdCLE9BQWU7QUFDdkMsY0FBSSxRQUFRLEtBQUssZ0JBQWdCLElBQUksTUFBTTtBQUMzQyxjQUFJLFVBQVUsUUFBVztBQUN2QixvQkFBUSxDQUFDLEtBQUs7QUFBQSxVQUNoQixPQUFPO0FBQ0wsa0JBQU0sS0FBSyxLQUFLO0FBQUEsVUFDbEI7QUFDQSxlQUFLLGdCQUFnQixJQUFJLFFBQVEsS0FBSztBQUFBLFFBQ3hDO0FBQUE7QUFBQSxNQUlGO0FBRUEsTUFBTSxpQkFBTixNQUFxQjtBQUFBLFFBQ25CLFlBQ0UsUUFDZ0IsVUFDaEI7QUFEZ0I7QUFFaEIsZUFBSyxjQUFjO0FBQ25CLGVBQUssZUFBZSxvQkFBSSxJQUF3QjtBQUNoRCxlQUFLLE1BQU0sSUFBSSxNQUFrQjtBQUNqQyxlQUFLLGFBQWEsQ0FBQztBQUduQixjQUFJLENBQUMsS0FBSyxHQUFHLElBQUksU0FBUyxTQUFTLElBQUksSUFBSSxTQUFTLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7QUFDbEYsY0FBSSxDQUFDLElBQUksTUFBTSxPQUFPLGNBQWMsQ0FBQyxHQUFHO0FBQ3RDLGtCQUFNLElBQUksTUFBTSxrQkFBa0I7QUFBQSxVQUNwQztBQUNBLGdCQUFNLGFBQWEsSUFBSSxNQUFNLEdBQUc7QUFDaEMscUJBQVcsUUFBUSxDQUFDLFdBQVcsVUFBVTtBQUN2QyxrQkFBTSxPQUFPLE9BQU8sS0FBSyxFQUFFLEtBQUssTUFBTTtBQUN0QyxnQkFBSSxDQUFDLFVBQVUsTUFBTSxPQUFPLGVBQWUsQ0FBQyxHQUFHO0FBQzdDLG9CQUFNLElBQUksTUFBTSxrQkFBa0I7QUFBQSxZQUNwQztBQUNBLGtCQUFNLGFBQWEsS0FBSyxZQUFZLFdBQVcsTUFBTSxNQUFNLEtBQUs7QUFDaEUsaUJBQUssSUFBSSxLQUFLLFVBQVU7QUFBQSxVQUMxQixDQUFDO0FBR0QsY0FBSSxRQUFRLElBQUk7QUFFZCxtQkFBTyxDQUFDLEdBQUcsS0FBSyxhQUFhLFFBQVEsQ0FBQyxFQUNuQyxPQUFPLENBQUMsQ0FBQyxLQUFLLElBQUksTUFBTSxLQUFLLFVBQVUsS0FBSyxRQUFRLEtBQUssRUFDekQsSUFBSSxDQUFDLENBQUMsR0FBRyxNQUFNLEdBQUcsRUFDbEIsS0FBSyxFQUFFO0FBQUEsVUFDWixPQUFPO0FBQ0wsZ0JBQUksQ0FBQyxJQUFJLE1BQU0sT0FBTyxXQUFXLENBQUMsR0FBRztBQUNuQyxvQkFBTSxJQUFJLE1BQU0sYUFBYTtBQUFBLFlBQy9CO0FBQUEsVUFDRjtBQUdBLGdCQUFNLGFBQWEsSUFBSSxNQUFNLE9BQU8sZUFBZSxHQUFHLENBQUM7QUFDdkQsc0JBQVksUUFBUSxDQUFDLFdBQVc7QUFDOUIsZ0JBQUksV0FBVyxPQUFPO0FBQ3BCLG1CQUFLLGFBQWEsS0FBSyxXQUFXLE9BQU8sS0FBSyxZQUFZO0FBQUEsWUFDNUQsT0FBTztBQUNMLG9CQUFNLE9BQU8sS0FBSyxhQUFhLElBQUksTUFBTTtBQUN6QyxrQkFBSSxTQUFTLFFBQVc7QUFDdEIsc0JBQU0sSUFBSSxNQUFNLG9CQUFvQjtBQUFBLGNBQ3RDO0FBQ0EsbUJBQUssV0FBVyxLQUFLLEtBQUssUUFBUTtBQUFBLFlBQ3BDO0FBQUEsVUFDRixDQUFDO0FBQ0QsZUFBSyxNQUFNLEtBQUssWUFBWSxLQUFLLE9BQU8sS0FBSyxVQUFVO0FBQUEsUUFDekQ7QUFBQTtBQUFBO0FBQUEsUUFHQSxVQUFVLFFBQWdCLFVBQWtCLFlBQW9CO0FBQzlELGNBQUksT0FBTyxLQUFLLGFBQWEsSUFBSSxNQUFNO0FBQ3ZDLGNBQUksU0FBUyxRQUFXO0FBQ3RCLGdCQUFJLEtBQUssYUFBYSxZQUFZLEtBQUssVUFBVSxHQUFHO0FBQ2xELG9CQUFNLElBQUksTUFBTSxvQkFBb0I7QUFBQSxZQUN0QyxPQUFPO0FBQ0wsbUJBQUs7QUFDTCxtQkFBSyxhQUFhLEtBQUssVUFBVTtBQUFBLFlBQ25DO0FBQUEsVUFDRixPQUFPO0FBQ0wsbUJBQU8sRUFBRSxPQUFPLEdBQUcsVUFBVSxjQUFjLENBQUMsVUFBVSxFQUFFO0FBQUEsVUFDMUQ7QUFDQSxlQUFLLGFBQWEsSUFBSSxRQUFRLElBQUk7QUFBQSxRQUNwQztBQUFBO0FBQUEsUUFHQSxZQUFZLE1BQWMsU0FBa0IsTUFBeUIsUUFBUSxJQUFnQjtBQUMzRixnQkFBTSxPQUFPLEtBQUs7QUFDbEIsY0FBSSxXQUFXO0FBQ2YsY0FBSSxlQUFlLENBQUM7QUFDcEIsY0FBSSxVQUFVO0FBRWQsY0FBSSxDQUFDLEtBQUssTUFBTSxPQUFPLGVBQWUsQ0FBQyxLQUFLLENBQUMsV0FBVyxTQUFTLElBQUk7QUFDbkUsa0JBQU0sSUFBSSxNQUFNLGtCQUFrQjtBQUFBLFVBQ3BDO0FBQ0EsZ0JBQU0sZUFBZSxLQUFLLE1BQU0sT0FBTyxlQUFlLEdBQUcsQ0FBQztBQUMxRCxnQkFBTSxhQUFhLElBQUksV0FBVyxLQUFLO0FBRXZDLHdCQUFjLFFBQVEsQ0FBQyxRQUFnQixNQUFjO0FBQ25ELGdCQUFJLFdBQVcsT0FBTztBQUNwQixrQkFBSSxVQUFVO0FBQ1osc0JBQU0sSUFBSSxNQUFNLDZDQUE2QztBQUFBLGNBQy9EO0FBQ0EseUJBQVc7QUFDWCxvQkFBTSxvQkFBb0IsT0FBTyxhQUFhLFNBQVM7QUFDdkQsa0JBQUksb0JBQW9CLEdBQUc7QUFDekIsc0JBQU0sSUFBSSxNQUFNLHdCQUF3QjtBQUFBLGNBQzFDO0FBQ0EsNkJBQWUsS0FBSyxNQUFNLFNBQVMsVUFBVSxpQkFBaUI7QUFDOUQsa0JBQUksS0FBSyxhQUFhO0FBQ3BCLG9CQUNFLEtBQUssYUFBYSxXQUFXLGFBQWEsVUFDMUMsS0FBSyxhQUFhLFNBQVMsTUFBTSxhQUFhLFNBQVMsR0FDdkQ7QUFDQSx3QkFBTSxJQUFJLE1BQU0sOEJBQThCO0FBQUEsZ0JBQ2hEO0FBQUEsY0FDRixXQUFXLFNBQVM7QUFDbEIscUJBQUssY0FBYztBQUNuQixxQkFBSyxlQUFlO0FBQUEsY0FDdEIsT0FBTztBQUNMLHNCQUFNLElBQUksTUFBTSx1Q0FBdUM7QUFBQSxjQUN6RDtBQUVBLHVCQUFTLElBQUksR0FBRyxJQUFJLGFBQWEsUUFBUSxLQUFLO0FBQzVDLHNCQUFNRSxVQUFTLE9BQU8sYUFBYSxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUM7QUFDeEQsMkJBQVcsVUFBVUEsU0FBUSxJQUFJLENBQUM7QUFDbEMscUJBQUssVUFBVUEsU0FBUSxLQUFLLFNBQVMsR0FBRyxLQUFLO0FBQUEsY0FDL0M7QUFBQSxZQUNGLE9BQU87QUFDTCx5QkFBVyxVQUFVLFFBQVEsS0FBSyxLQUFLLGNBQWMsS0FBSyxhQUFhLFNBQVMsSUFBSSxFQUFFO0FBQ3RGLG1CQUFLLFVBQVUsUUFBUSxLQUFLLFNBQVMsR0FBRyxLQUFLO0FBQUEsWUFDL0M7QUFBQSxVQUNGLENBQUM7QUFDRCxpQkFBTztBQUFBLFFBQ1Q7QUFBQTtBQUFBLE1BUUY7QUFFQSxNQUFNLFlBQVksQ0FBQyxTQUF5QixPQUFPO0FBRW5ELE1BQU0sMEJBQTBCLENBQzlCLGFBQ0EsVUFDQSxnQkFDQSxnQkFDZ0I7QUFDaEIsY0FBTSxRQUFRLFlBQVksSUFBSSxDQUFDLFNBQVMsS0FBSyxNQUFNO0FBQ25ELGNBQU0sWUFBWSxNQUFNLElBQUksQ0FBQyxNQUFNLFVBQVUsY0FBYyxRQUFRLEtBQUssSUFBSSxVQUFVLElBQUksQ0FBQztBQUMzRixjQUFNLGFBQWEsVUFBVSxLQUFLLFdBQVc7QUFDN0MsY0FBTSxTQUFTLGVBQWUsVUFBVSxVQUFVLFlBQVksTUFBTTtBQUNwRSxjQUFNLGtCQUFrQixDQUFDLEdBQUcsZUFBZSxhQUFhLEtBQUssQ0FBQyxFQUFFO0FBQUEsVUFDOUQsQ0FBQyxXQUFXLENBQUMsZUFBZSxJQUFJLGdCQUFnQixJQUFJLE1BQU07QUFBQSxRQUM1RDtBQUNBLGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQ3RELGdCQUFNLFVBQW9CLENBQUM7QUFDM0IsZ0JBQU0sV0FBVztBQUNqQixnQkFBTSxVQUFVO0FBQ2hCLGdCQUFNLFlBQVk7QUFDbEIsZ0JBQU0sc0JBQWdDLENBQUM7QUFDdkMsZ0JBQU0sdUJBQWlDLENBQUM7QUFDeEMsZ0JBQU0sdUJBQWlDLENBQUM7QUFDeEMsZ0JBQU0sa0JBQTRCLENBQUM7QUFDbkMsZ0JBQU0seUJBQXlCLGVBQWUsYUFBYSxTQUFTLGVBQWUsSUFBSSxnQkFBZ0I7QUFDdkcseUJBQWUsYUFBYSxRQUFRLENBQUMsTUFBTSxXQUFXO0FBQ3BELGdCQUFJLGVBQWUsSUFBSSxnQkFBZ0IsSUFBSSxNQUFNLEdBQUc7QUFDbEQsb0JBQU0sY0FBYyxlQUFlLElBQUksZ0JBQWdCLElBQUksTUFBTSxJQUFJLENBQUM7QUFDdEUsa0JBQUksZ0JBQWdCLFFBQVc7QUFDN0IsK0JBQWUsSUFBSSxRQUFRLENBQUMsTUFBTSxNQUFNO0FBQ3RDLHNCQUFJLEtBQUssYUFBYSxTQUFTLENBQUMsR0FBRztBQUNqQywwQkFBTSxVQUFVLEtBQUssZ0JBQWdCLElBQUksTUFBTTtBQUMvQyx3QkFBSSxZQUFZLFFBQVc7QUFDekIsNEJBQU0sSUFBSSxNQUFNLHNCQUFzQjtBQUFBLG9CQUN4QztBQUNBLDRCQUFRLFFBQVEsQ0FBQyxVQUFVO0FBQ3pCLDhCQUFRO0FBQUEsd0JBQ04sR0FBRyxVQUFVLENBQUMsRUFBRTtBQUFBLDBCQUNkLFFBQVEsQ0FBQztBQUFBLDBCQUNUO0FBQUEsMEJBQ0EsT0FBTyxXQUFXLGlCQUFpQixXQUFXO0FBQUEsd0JBQ2hELENBQUM7QUFBQSxzQkFDSDtBQUFBLG9CQUNGLENBQUM7QUFBQSxrQkFDSDtBQUFBLGdCQUNGLENBQUM7QUFBQSxjQUNIO0FBQUEsWUFDRixPQUFPO0FBQ0wsNkJBQWUsSUFBSSxRQUFRLENBQUMsTUFBTSxNQUFNO0FBQ3RDLG9CQUFJLEtBQUssYUFBYSxTQUFTLENBQUMsR0FBRztBQUNqQyx3QkFBTSxVQUFVLEtBQUssZ0JBQWdCLElBQUksTUFBTTtBQUMvQyxzQkFBSSxZQUFZLFFBQVc7QUFDekIsMEJBQU0sSUFBSSxNQUFNLHNCQUFzQjtBQUFBLGtCQUN4QztBQUNBLDBCQUFRLFFBQVEsQ0FBQyxVQUFVO0FBQ3pCLHdDQUFvQixLQUFLLEdBQUcsVUFBVSxDQUFDLEVBQUUsV0FBVyxRQUFRLENBQUMsV0FBVyxPQUFPLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRTtBQUFBLGtCQUMvRixDQUFDO0FBQ0Qsa0NBQWdCLEtBQUssV0FBVyxVQUFVLENBQUMsRUFBRSxhQUFhLFFBQVEsQ0FBQyxTQUFTLENBQUMsR0FBRztBQUFBLGdCQUNsRjtBQUFBLGNBQ0YsQ0FBQztBQUNELG1DQUFxQjtBQUFBLGdCQUNuQixXQUFXLE1BQU0sY0FBYyxNQUFNLGVBQWUsVUFBVSxNQUFNLENBQUMsS0FBSyxNQUFNO0FBQUEsY0FDbEY7QUFDQSxtQ0FBcUIsS0FBSyxHQUFHO0FBQUEsWUFDL0I7QUFBQSxVQUNGLENBQUM7QUFDRCxnQkFBTUMsYUFBWSx5QkFDZDtBQUFBLFlBQ0UsR0FBRztBQUFBLFlBQ0gsYUFBYSxVQUFVLElBQUksQ0FBQyxVQUFVLE1BQU0sU0FBUyxhQUFhLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRSxLQUFLLEtBQUssQ0FBQztBQUFBLFVBQ3BHLElBQ0E7QUFBQSxZQUNFLEdBQUc7QUFBQSxZQUNIO0FBQUEsWUFDQSxHQUFHO0FBQUEsWUFDSCxHQUFHO0FBQUEsWUFDSDtBQUFBLFlBQ0EsR0FBRztBQUFBLFlBQ0g7QUFBQSxZQUNBLEdBQUc7QUFBQSxVQUNMO0FBQ0osaUJBQU87QUFBQSxjQUNHLGFBQ0MsaUJBQWlCLGdCQUFnQixJQUFJLENBQUMsWUFBWSxFQUFFLE1BQU0sR0FBRyxVQUFVLE1BQU0sQ0FBQyxJQUFJLE1BQU0sTUFBTSxFQUFFLENBQUMsRUFDakcsZ0JBQWdCLGNBQWMsS0FBSyxFQUNuQyxpQkFBaUIsR0FBRyxXQUFXLE1BQU0sQ0FBQztBQUFBO0FBQUEsY0FFdkMsYUFBYSxVQUFVLENBQUM7QUFBQSxjQUN4QixhQUFhLHNDQUFzQyxxQkFBcUIsQ0FBQztBQUFBLGtDQUNyRCxPQUFPLGdCQUFnQixZQUFZLENBQUM7QUFBQSxjQUN4RCxVQUFVLElBQUksQ0FBQyxNQUFNLE1BQU0sWUFBWSxDQUFDLFlBQVksVUFBVSxDQUFDLEVBQUUsS0FBSyxPQUFPLEdBQUcsRUFBRSxLQUFLLElBQUksQ0FBQztBQUFBLGNBQzVGQSxXQUFVLEtBQUssSUFBSSxDQUFDO0FBQUEsY0FDcEIsT0FBTyxZQUFZLGNBQWMsS0FBSyxDQUFDO0FBQUE7QUFBQSxRQUVuRDtBQUNBLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWEsRUFBRSxNQUFNLGVBQWUsVUFBVSxtQkFBbUIsWUFBWSxJQUFJLE1BQU0sTUFBTSxFQUFFO0FBQUEsVUFDL0YsWUFBWSxNQUFNO0FBR2hCLGtCQUFNLHNCQUF3QyxnQkFDM0MsT0FBTyxDQUFDLFdBQVcsZUFBZSxhQUFhLElBQUksTUFBTSxDQUFDLEVBQzFELElBQUksQ0FBQyxZQUFZLEVBQUUsdUJBQXVCLE1BQU0sZUFBZSxhQUFhLElBQUksTUFBTSxHQUFHLFlBQVksRUFBRSxFQUFFO0FBQzVHLGdDQUFvQixLQUFLLEVBQUUsdUJBQXVCLE1BQU0sV0FBVyxDQUFDO0FBQ3BFLGtCQUFNLGtCQUFvQyxZQUN2QyxJQUFJLENBQUMsTUFBTSxNQUFNLENBQUMsR0FBRywyQkFBMkIsSUFBSSxDQUFDLENBQUMsRUFDdEQsT0FBTyxDQUFDLEtBQUsseUJBQXlCLElBQUksT0FBTyxvQkFBb0IsR0FBRyxtQkFBbUI7QUFDOUYsNEJBQWdCLEtBQUssR0FBRywyQkFBMkIsV0FBVyxDQUFDO0FBQy9ELG1CQUFPO0FBQUEsY0FDTCxTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsU0FBUyxDQUFDO0FBQUEsY0FDekMsZUFBZSxFQUFFLEdBQUcsS0FBSztBQUFBLGdCQUFLLGFBQWE7QUFBQTtBQUFBLGNBQXVCLEVBQUU7QUFBQSxjQUNwRTtBQUFBLFlBQ0Y7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxTQUFTLENBQUMsU0FBeUIsZUFBdUM7QUFDckYsY0FBTSxpQkFBaUIsSUFBSSxlQUFlLFFBQVEsUUFBUSxXQUFXLFFBQVE7QUFDN0UsY0FBTSxjQUFjLGVBQWU7QUFDbkMsY0FBTSxjQUFjLFFBQVEsT0FBTyxJQUFJLENBQUMsT0FBTyxNQUFNLE1BQU0sSUFBSTtBQUMvRCxnQkFBUSxRQUFRLHdCQUF3QixhQUFhLFFBQVEsT0FBTyxDQUFDLEVBQUUsVUFBVSxnQkFBZ0IsV0FBVyxDQUFDO0FBQUEsTUFDL0c7QUFFTyxNQUFNLHdCQUF3QixDQUFDLGVBQTBEO0FBQzlGLGNBQU0sV0FBWSxXQUFXLFNBQW9CLFFBQVEsUUFBUSxFQUFFO0FBQ25FLGVBQU8sNEJBQTRCLEVBQUUsU0FBUyxDQUFDO0FBQUEsTUFDakQ7QUFBQTtBQUFBOzs7QUN6VEEsTUFVTUMsa0JBb0JBLGtCQVlBQyx1QkFHQSx5QkFtRU87QUFoSGI7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUdBO0FBRUEsTUFBTUQsbUJBQWlCLENBQUMsV0FBd0M7QUFDOUQsWUFBSSxDQUFDLFVBQVUsT0FBTyxXQUFXLEdBQUc7QUFDbEMsZ0JBQU0sSUFBSSxNQUFNLDBCQUEwQjtBQUFBLFFBQzVDO0FBQ0EsY0FBTSxhQUFhLE9BQU8sQ0FBQyxFQUFFO0FBQzdCLGNBQU0sUUFBUSxNQUFNLEtBQUssT0FBTyxDQUFDLEVBQUUsaUJBQWlCLEdBQUcsTUFBTTtBQUU3RCxZQUFJLGFBQWEsTUFBTSxTQUFTLFdBQVcsU0FBUyxJQUFJLE1BQU0sU0FBUyxXQUFXO0FBQ2xGLFlBQUksa0JBQWtCLFdBQVcsU0FBUyxNQUFNLFNBQVMsSUFBSSxXQUFXLFNBQVMsTUFBTTtBQUN2RixlQUFPLGFBQWEsTUFBTSxVQUFVLGtCQUFrQixXQUFXLFFBQVEsRUFBRSxZQUFZLEVBQUUsaUJBQWlCO0FBQ3hHLGNBQ0UsTUFBTSxVQUFVLE1BQU0sV0FBVyxlQUFlLEtBQ2hELE1BQU0sVUFBVSxNQUFNLEtBQ3RCLFdBQVcsZUFBZSxNQUFNLEdBQ2hDO0FBQ0Esa0JBQU0sSUFBSSxNQUFNLG9EQUFvRDtBQUFBLFVBQ3RFO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFQSxNQUFNLG1CQUFtQixDQUFDLFFBQTJCLFdBQXdDO0FBQzNGLGNBQU0sT0FBTyxPQUFPLFNBQVMsT0FBTztBQUNwQyxjQUFNLFFBQWtCLENBQUM7QUFDekIsaUJBQVMsSUFBSSxHQUFHLElBQUksTUFBTSxFQUFFLEdBQUc7QUFDN0IsZ0JBQU0sS0FBSyxPQUFPLENBQUMsQ0FBQztBQUFBLFFBQ3RCO0FBQ0EsaUJBQVMsSUFBSSxHQUFHLElBQUksT0FBTyxRQUFRLEVBQUUsR0FBRztBQUN0QyxnQkFBTSxLQUFLLE9BQU8sQ0FBQyxNQUFNLElBQUksT0FBTyxJQUFJLElBQUksSUFBSSxPQUFPLENBQUMsQ0FBQztBQUFBLFFBQzNEO0FBQ0EsZUFBTztBQUFBLE1BQ1Q7QUFFQSxNQUFNQyx3QkFBdUIsQ0FBQyxZQUErQixVQUMzRCxXQUFXLFNBQVMsTUFBTSxTQUFTLGlCQUFpQixZQUFZLEtBQUssSUFBSSxpQkFBaUIsT0FBTyxVQUFVO0FBRTdHLE1BQU0sMEJBQTBCLENBQUMsV0FBK0M7QUFDOUUsY0FBTSxhQUFhLE9BQU8sQ0FBQyxFQUFFO0FBQzdCLGNBQU0sUUFBUSxNQUFNLEtBQUssT0FBTyxDQUFDLEVBQUUsaUJBQWlCLEdBQUcsTUFBTTtBQUM3RCxjQUFNLGNBQXdCQSxzQkFBcUIsWUFBWSxLQUFLO0FBQ3BFLGNBQU0sV0FBVyxPQUFPLENBQUMsRUFBRTtBQUMzQixjQUFNLGlCQUFpQiw2QkFBOEIsVUFBVSxLQUFLLFVBQVUsTUFBTTtBQUNwRixjQUFNLGNBQ0osNEJBQTZCLElBQUksV0FBVyxTQUFTLEtBQUssV0FBVyxXQUFXLFNBQVMsQ0FBQyxJQUFJLE1BQU0sSUFBSSxJQUFJO0FBQzlHLGNBQU0sYUFBYSxpQkFDZixJQUNBLFlBQVksU0FBUyxLQUFLLFlBQVksWUFBWSxTQUFTLENBQUMsSUFBSSxNQUFNLElBQ3BFLElBQ0E7QUFDTixjQUFNLGFBQWEsS0FBSyxLQUFLLFVBQVUsS0FBSyxXQUFXLElBQUksVUFBVTtBQUVyRSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxnQkFBTSxRQUFRLGNBQWMsU0FBUyxVQUFVLFdBQVcsUUFBUSxXQUFXO0FBQzdFLGdCQUFNLFNBQVMsZUFBZSxVQUFVLFVBQVUsWUFBWSxRQUFRLFVBQVU7QUFDaEYsY0FBSTtBQUNKLGNBQUksMkJBQTRCO0FBQzlCLGtCQUFNLG1CQUFtQixDQUFDLFFBQWdCLEdBQVcsV0FBVyxPQUFPO0FBQUEsNkJBQ2hELENBQUMsTUFBTSxPQUFPLGdCQUFnQixrQkFBa0IsQ0FBQyxHQUFHLENBQUM7QUFBQSxzQkFDNUQsQ0FBQyxNQUFNLE1BQU0sMkJBQTJCLGdCQUFnQixDQUFDLElBQUksTUFBTSxDQUFDO0FBQUEscUJBQ3JFLENBQUMsWUFBWSxDQUFDO0FBQUEseUJBQ1YsQ0FBQyxZQUFZLENBQUM7QUFBQSxZQUMzQixNQUFNLElBQUksQ0FBQyxPQUFPLFFBQVEsSUFBSSxNQUFNLFlBQVksUUFBUSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUM7QUFBQTtBQUVoRix5QkFBYTtBQUFBLDBDQUN1QixVQUFVO0FBQUE7QUFBQSxVQUUxQyxpQkFBaUIsUUFBUSxHQUFHLEtBQUssQ0FBQztBQUFBLFVBQ2xDLGlCQUFpQixRQUFRLEdBQUcsS0FBSyxDQUFDO0FBQUEsVUFDbEMsaUJBQWlCLFFBQVEsR0FBRyxLQUFLLENBQUM7QUFBQSxVQUNsQyxpQkFBaUIsUUFBUSxHQUFHLEtBQUssQ0FBQztBQUFBLFVBQ2xDLE9BQU8sWUFBWSxjQUFjLE1BQU0sQ0FBQztBQUFBO0FBQUEsVUFFOUMsT0FBTztBQUNMLHlCQUFhO0FBQUEsOEJBQ1csT0FBTyxnQkFBZ0IsZ0JBQWdCLFVBQVUsRUFBRSxDQUFDO0FBQUEsNEJBQ3RELE1BQU0sMkJBQTJCLGlCQUFpQixNQUFNLENBQUM7QUFBQSxxQkFDaEUsT0FBTyxLQUFLLEtBQUssSUFBSSxNQUFNLFlBQVksaUJBQWlCLFdBQVcsRUFBRSxDQUFDO0FBQUEsVUFDakYsT0FBTyxZQUFZLGNBQWMsTUFBTSxDQUFDO0FBQUE7QUFBQSxVQUU5QztBQUNBLGlCQUFPO0FBQUEsTUFDTCxhQUFhLGdCQUFnQixZQUFZLEtBQUssRUFBRSxpQkFBaUIsT0FBTyxNQUFNLENBQUM7QUFBQSxNQUMvRSxhQUFhLFVBQVUsQ0FBQztBQUFBLE1BQ3hCLGFBQWEsc0NBQXNDLG1CQUFtQixDQUFDO0FBQUEsTUFDdkUsVUFBVTtBQUFBLFFBQ2Q7QUFFQSxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEdBQUcsMkJBQTJCLFlBQVksV0FBVztBQUFBLFFBQ3ZEO0FBQ0EsZUFBTztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sYUFBYSxFQUFFLE1BQU0sR0FBRyxZQUFZLE1BQU0sSUFBSSxXQUFXLEdBQUcsVUFBVSxJQUFJLG1CQUFtQixDQUFDLE1BQU0sRUFBRTtBQUFBLFVBQ3RHO0FBQUEsVUFDQSxZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxPQUFPLENBQUMsRUFBRSxTQUFTLENBQUM7QUFBQSxZQUM3RCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxhQUFhO0FBQUE7QUFBQSxZQUF1QixFQUFFO0FBQUEsWUFDcEU7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLFNBQVMsQ0FBQyxZQUFrQztBQUN2RCxRQUFBRCxpQkFBZSxRQUFRLE1BQU07QUFDN0IsZ0JBQVEsUUFBUSx3QkFBd0IsUUFBUSxNQUFNLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFBQSxNQUMxRTtBQUFBO0FBQUE7OztBQ25IQSxNQW9CTSwyQkFzRE9FO0FBMUViO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFHQTtBQVFBO0FBSUEsTUFBTSw0QkFBNEIsQ0FBQyxpQkFBcUQ7QUFDdEYsY0FBTSxXQUFXLGFBQWEsQ0FBQyxFQUFFO0FBQ2pDLGNBQU0sYUFBYSxVQUFVLEtBQUssYUFBYSxDQUFDLEVBQUUsSUFBSTtBQUN0RCxjQUFNLGFBQWEsVUFBVSxLQUFLLGFBQWEsQ0FBQyxFQUFFLElBQUk7QUFFdEQsY0FBTSxVQUFVLGFBQWEsTUFBTTtBQUNuQyxjQUFNLGtCQUFrQixDQUFDLGlCQUF1QztBQUM5RCxnQkFBTSxJQUFJLGNBQWMsS0FBSyxVQUFVLENBQUMsQ0FBQyxHQUFHLENBQUM7QUFDN0MsZ0JBQU0sT0FBTyxjQUFjLFFBQVEsVUFBVSxDQUFDLENBQUMsR0FBRyxDQUFDO0FBQ25ELGdCQUFNLElBQUksZUFBZSxLQUFLLFVBQVUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztBQUU5QyxnQkFBTSxXQUE4QjtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxtQkFBbUIsTUFBTSxNQUFNO0FBQUEsWUFDdkMsRUFBRSxNQUFNLGFBQWEsTUFBTSxNQUFNO0FBQUEsVUFDbkM7QUFFQSxnQkFBTSxvQkFBb0IsQ0FBQyxNQUFxQjtBQUFBLGdCQUNwQyxDQUFDLG9DQUFvQyxDQUFDO0FBQUEsZ0JBQ3RDLENBQUMsTUFBTSxLQUFLLFlBQVksT0FBTyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUM7QUFDbkUsZ0JBQU0sb0JBQW9CLFVBQ3RCO0FBQUEsbUJBQ1csS0FBSyxZQUFZLHVDQUF1QyxDQUFDLE1BQ3BFLEdBQUcsa0JBQWtCLENBQUMsQ0FBQyxHQUFHLGtCQUFrQixDQUFDLENBQUMsR0FBRyxrQkFBa0IsQ0FBQyxDQUFDLEdBQUcsa0JBQWtCLENBQUMsQ0FBQztBQUFBLG1CQUNqRixFQUFFLEtBQUssS0FBSztBQUUzQixpQkFBTyxHQUFHLGFBQWEsaUJBQWlCLFFBQVEsRUFBRSxpQkFBaUIsR0FBRyxNQUFNLENBQUMsQ0FBQztBQUFBO0FBQUEsTUFFdEUsYUFBYSwwQkFBMEIsUUFBUSxDQUFDLENBQUM7QUFBQTtBQUFBLE1BRXZELGFBQWEsVUFBVSxjQUFjLENBQUM7QUFBQSxRQUNwQyxhQUFhLHNDQUFzQywwQkFBMEIsQ0FBQztBQUFBO0FBQUEsZ0JBRXRFLEVBQUUsWUFBWSxZQUFZLENBQUM7QUFBQSxRQUNuQyxpQkFBaUI7QUFBQTtBQUFBLFFBRWpCLEVBQUUsWUFBWSxjQUFvQixtQkFBbUIsTUFBTSxDQUFDLENBQUM7QUFBQTtBQUFBLFFBRW5FO0FBRUEsZUFBTztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sYUFBYSxFQUFFLE1BQU0sR0FBRyxPQUFPLElBQUksbUJBQW1CLENBQUMsUUFBUSxNQUFNLEVBQUU7QUFBQSxVQUN2RTtBQUFBLFVBQ0EsWUFBWSxDQUFDLFlBQVk7QUFBQSxZQUN2QixTQUFTLENBQUMsRUFBRSxNQUFNLE9BQU8sQ0FBQyxFQUFFLE1BQU0sVUFBVSxPQUFPLENBQUMsRUFBRSxTQUFTLENBQUM7QUFBQSxZQUNoRSxpQkFBaUI7QUFBQSxjQUNmLEVBQUUsdUJBQXVCLE1BQU0sS0FBSyxLQUFLLGFBQWEsQ0FBQyxFQUFFO0FBQUEsY0FDekQsRUFBRSx1QkFBdUIsTUFBTSxXQUFXO0FBQUEsWUFDNUM7QUFBQSxZQUNBLGVBQWUsRUFBRSxHQUFHLEtBQUssS0FBSyxhQUFhLGlCQUFpQixDQUFDLEVBQUU7QUFBQSxVQUNqRTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTUEsWUFBVyxDQUFDLFlBQWtDO0FBQ3pELFlBQUksUUFBUSxPQUFPLFNBQVMsS0FBSyxVQUFVLEtBQUssUUFBUSxPQUFPLENBQUMsRUFBRSxJQUFJLE1BQU0sR0FBRztBQUM3RSxVQUFNLFNBQVMsT0FBTztBQUFBLFFBQ3hCLE9BQU87QUFDTCxrQkFBUSxRQUFRLDBCQUEwQixRQUFRLE1BQU0sQ0FBQztBQUFBLFFBQzNEO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQ2hGQSxNQWVNQyxrQkFNQSx5QkF3R08sdUJBR0E7QUFoSWI7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUNBO0FBR0E7QUFNQSxNQUFNQSxtQkFBaUIsQ0FBQyxXQUF3QztBQUM5RCxZQUFJLENBQUMsVUFBVSxPQUFPLFdBQVcsR0FBRztBQUNsQyxnQkFBTSxJQUFJLE1BQU0sMkJBQTJCO0FBQUEsUUFDN0M7QUFBQSxNQUNGO0FBRUEsTUFBTSwwQkFBMEIsQ0FBQyxRQUErQixlQUE4QztBQUM1RyxjQUFNLGFBQWEsT0FBTyxDQUFDLEVBQUU7QUFDN0IsY0FBTSxlQUFlLE9BQU8sQ0FBQyxFQUFFO0FBRS9CLGNBQU0sWUFBWSxXQUFXO0FBQzdCLGNBQU0sT0FBTyxVQUFVLGNBQWMsV0FBVyxNQUFNLFNBQVM7QUFFL0QsY0FBTSxjQUFjLFdBQVcsTUFBTSxDQUFDO0FBQ3RDLG9CQUFZLE9BQU8sTUFBTSxHQUFHLEdBQUcsWUFBWTtBQUUzQyxjQUFNLGVBQWUsV0FBVyxJQUFJO0FBQ3BDLGNBQU0sYUFBYSxPQUFPLENBQUMsRUFBRSw0QkFBNkIsSUFBSTtBQUM5RCxjQUFNLGFBQWEsS0FBSyxLQUFLLFVBQVUsS0FBSyxXQUFXLElBQUksVUFBVTtBQUVyRSxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUscUJBQXNCLE1BQU0sYUFBYTtBQUFBLFVBQzNDLEVBQUUsdUJBQXVCLE1BQU0sS0FBSztBQUFBLFVBQ3BDLEdBQUcsMkJBQTJCLE9BQU8sQ0FBQyxFQUFFLE1BQU0sT0FBTyxDQUFDLEVBQUUsTUFBTSxXQUFXO0FBQUEsUUFDM0U7QUFFQSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxnQkFBTSxPQUFPLGNBQWMsUUFBUSxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLEtBQUssUUFBUSxVQUFVO0FBQ3hGLGdCQUFNLFVBQVUsY0FBYyxnQkFBZ0IsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU07QUFDdkYsZ0JBQU0sU0FBUyxlQUFlLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxZQUFZLFFBQVEsVUFBVTtBQUUxRixnQkFBTSxrQkFBa0IsQ0FBQyxNQUErQjtBQUN0RCxrQkFBTSxjQUFjLGFBQWE7QUFDakMsZ0JBQUksVUFBVSxxQkFBcUIsQ0FBQyxPQUFPLFFBQVEsS0FBSyxPQUFPO0FBQy9ELHFCQUFTLElBQUksR0FBRyxJQUFJLGFBQWEsS0FBSztBQUNwQyx5QkFBVyxHQUFHLGNBQWMsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxpQkFBaUIsQ0FBQyxFQUFFLE1BQy9FLFlBQVksU0FBUyxJQUFJLGdCQUFnQixDQUFDLG9CQUFvQixDQUFDLE1BQU0sZ0JBQWdCLENBQUMsRUFDeEY7QUFBQSxZQUNGO0FBQ0EsdUJBQVc7QUFBQSxtQkFDRSxDQUFDLE1BQU0sUUFBUSxhQUFhLGlCQUFpQixDQUFDLEVBQUUsQ0FBQztBQUFBLG1CQUNqRCxDQUFDO0FBQUEsaUJBQ0gsQ0FBQyxTQUFTLENBQUM7QUFBQTtBQUFBLDJCQUVELENBQUMsTUFBTSxLQUFLLEtBQUssT0FBTztBQUFBO0FBRTdDLHFCQUFTLElBQUksR0FBRyxJQUFJLEdBQUcsSUFBSSxXQUFXLEtBQUs7QUFDekMsa0JBQUksTUFBTSxNQUFNO0FBQ2QsMkJBQVcsR0FBRyxZQUFZLElBQUksY0FBYyxDQUFDLElBQUksQ0FBQyxNQUFNLGNBQWMsQ0FBQyxFQUFFLGFBQWEsQ0FBQztBQUN2RixxQkFBSztBQUFBLGNBQ1AsT0FBTztBQUNMLDJCQUFXLEdBQUcsWUFBWSxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsTUFBTSxjQUFjLENBQUMsRUFBRSxNQUN2RSxZQUFZLFNBQVMsSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxnQkFBZ0IsQ0FBQyxFQUN4RTtBQUNBO0FBQUEsY0FDRjtBQUFBLFlBQ0Y7QUFDQSxtQkFBTztBQUFBLFVBQ1Q7QUFDQSxjQUFJO0FBQ0osY0FBSSxPQUFPLENBQUMsRUFBRSwyQkFBNEI7QUFDeEMsa0JBQU0sbUJBQW1CLENBQUMsUUFBZ0IsR0FBVyxXQUFXLE9BQU87QUFBQSw2QkFDaEQsQ0FBQyxNQUFNLE9BQU8sZ0JBQWdCLGtCQUFrQixDQUFDLEdBQUcsQ0FBQztBQUFBLFlBQ3RFLGdCQUFnQixDQUFDLENBQUM7QUFBQSxzQkFDUixDQUFDLE1BQU0sS0FBSyxnQkFBZ0IsY0FBYyxDQUFDLEVBQUUsQ0FBQztBQUFBLHFCQUMvQyxDQUFDLFlBQVksQ0FBQztBQUFBLHlCQUNWLENBQUMsWUFBWSxDQUFDO0FBQUEsWUFDM0IsTUFBTSxJQUFJLENBQUMsT0FBTyxRQUFRLElBQUksS0FBSyxZQUFZLFFBQVEsQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDO0FBQUE7QUFFL0UseUJBQWE7QUFBQSwwQ0FDdUIsVUFBVTtBQUFBO0FBQUEsVUFFMUMsaUJBQWlCLFNBQVMsR0FBRyxLQUFLLENBQUM7QUFBQSxVQUNuQyxpQkFBaUIsU0FBUyxHQUFHLEtBQUssQ0FBQztBQUFBLFVBQ25DLGlCQUFpQixTQUFTLEdBQUcsS0FBSyxDQUFDO0FBQUEsVUFDbkMsaUJBQWlCLFNBQVMsR0FBRyxLQUFLLENBQUM7QUFBQSxVQUNuQyxPQUFPLFlBQVksY0FBYyxPQUFPLENBQUM7QUFBQTtBQUFBLFVBRS9DLE9BQU87QUFDTCx5QkFBYTtBQUFBLDRCQUNTLE9BQU8sZ0JBQWdCLFlBQVksQ0FBQztBQUFBLFFBQ3hELGdCQUFnQixFQUFFLENBQUM7QUFBQSxvQkFDUCxLQUFLLGFBQWEsYUFBYSxDQUFDO0FBQUEsUUFDNUMsT0FBTyxZQUFZLGNBQWMsT0FBTyxDQUFDO0FBQUE7QUFBQSxVQUU3QztBQUNBLGlCQUFPO0FBQUEsUUFDSCxhQUNDLGdCQUFnQixjQUFjLEtBQUssRUFDbkMsZ0JBQWdCLGdCQUFnQixLQUFLLEVBQ3JDLGdCQUFnQixRQUFRLEtBQUssRUFDN0IsaUJBQWlCLE1BQU0sU0FBUyxNQUFNLENBQUM7QUFBQSxRQUN4QyxhQUFhLFVBQVUsQ0FBQztBQUFBLFVBQ3RCLGFBQWEsc0NBQXNDLHFCQUFxQixDQUFDO0FBQUEsVUFDekUsVUFBVTtBQUFBO0FBQUEsUUFFbEI7QUFDQSxlQUFPO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixhQUFhLEVBQUUsTUFBTSxXQUFXLFVBQVUsbUJBQW1CLENBQUMsUUFBUSxNQUFNLEVBQUU7QUFBQSxVQUM5RSxZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxPQUFPLENBQUMsRUFBRSxTQUFTLENBQUM7QUFBQSxZQUM3RCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxhQUFhO0FBQUE7QUFBQSxZQUF1QixFQUFFO0FBQUEsWUFDcEU7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSx3QkFBd0IsQ0FBQyxlQUNwQyw0QkFBNEIsRUFBRSxNQUFNLFdBQVcsS0FBZSxDQUFDO0FBRTFELE1BQU0sU0FBUyxDQUFDLFNBQXlCLGVBQXVDO0FBQ3JGLGNBQU0sU0FBUyxRQUFRO0FBQ3ZCLFFBQUFBLGlCQUFlLE1BQU07QUFDckIsZ0JBQVEsUUFBUSx3QkFBd0IsUUFBUSxRQUFRLFVBQVUsQ0FBQztBQUFBLE1BQ3JFO0FBQUE7QUFBQTs7O0FDcElBLE1BZU0scUJBa0ZPLFVBMkVBO0FBNUtiO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFJQTtBQU1BLE1BQU0sc0JBQXNCLENBQzFCLFNBQ0EsYUFDQSx3QkFDQSxXQUNBLFdBQ0EsV0FDQSxtQkFDQSxrQkFDQSxpQkFDRztBQUNILGNBQU0sa0JBQW9DO0FBQUEsVUFDeEMsRUFBRSx1QkFBdUIsTUFBTSxVQUFVO0FBQUEsVUFDekMsRUFBRSx1QkFBdUIsTUFBTSxVQUFVO0FBQUEsVUFDekMsRUFBRSx1QkFBdUIsTUFBTSxVQUFVO0FBQUEsVUFDekMsRUFBRSx1QkFBdUIsTUFBTSx1QkFBdUI7QUFBQSxVQUN0RCxFQUFFLHVCQUF1QixNQUFNLGtCQUFrQjtBQUFBLFVBQ2pELEVBQUUsdUJBQXVCLE1BQU0saUJBQWlCO0FBQUEsVUFDaEQsRUFBRSx1QkFBdUIsTUFBTSxhQUFhO0FBQUEsUUFDOUM7QUFFQSxjQUFNLGNBQWMsQ0FBQyxTQUFTO0FBQzlCLHdCQUFnQixLQUFLLEdBQUcsMkJBQTJCLFlBQVksTUFBTSxXQUFXLENBQUM7QUFFakYsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFDdEQsZ0JBQU0sVUFBVSxjQUFjLGdCQUFnQixZQUFZLFVBQVUsWUFBWSxLQUFLLE1BQU07QUFDM0YsZ0JBQU0sU0FBUyxlQUFlLDZDQUE2QyxHQUFHLENBQUM7QUFDL0UsZ0JBQU0sWUFBWSxDQUFDLFNBQVMsTUFBTTtBQUNsQyxnQkFBTSxXQUE4QjtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxlQUFlLE1BQU0sTUFBTTtBQUFBLFlBQ25DLEVBQUUsTUFBTSxjQUFjLE1BQU0sTUFBTTtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxjQUFjLE1BQU0sT0FBTyxRQUFRLFVBQVUsT0FBTztBQUFBLFlBQzVELEVBQUUsTUFBTSw4QkFBOEIsTUFBTSxPQUFPLFFBQVEsdUJBQXVCLE9BQU87QUFBQSxZQUN6RixFQUFFLE1BQU0sd0JBQXdCLE1BQU0sTUFBTTtBQUFBLFlBQzVDLEVBQUUsTUFBTSxzQkFBc0IsTUFBTSxNQUFNO0FBQUEsWUFDMUMsRUFBRSxNQUFNLGtCQUFrQixNQUFNLE1BQU07QUFBQSxVQUN4QztBQUNBLGlCQUFPO0FBQUEsSUFDUCxhQUFhLGlCQUFpQixRQUFRLEVBQUUsaUJBQWlCLEdBQUcsU0FBUyxDQUFDO0FBQUEsSUFDdEUsYUFBYSxVQUFVLENBQUM7QUFBQSxNQUN0QixhQUFhLHNDQUFzQyxzQkFBc0IsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFVBV3RFLFVBQVUsV0FBVyxJQUNqQix1Q0FDQSxtREFDTjtBQUFBO0FBQUEsUUFHQSx1QkFBdUIsV0FBVyxJQUM5QiwrRUFDQSxxRkFDTjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFLSjtBQUVBLGVBQU8sUUFBUTtBQUFBLFVBQ2I7QUFBQSxZQUNFLE1BQU07QUFBQSxZQUNOLGFBQWEsRUFBRSxNQUFNLEdBQUcsVUFBVSxNQUFNLElBQUksdUJBQXVCLE1BQU0sSUFBSSxtQkFBbUIsQ0FBQyxNQUFNLEVBQUU7QUFBQSxZQUN6RyxZQUFZLE9BQU87QUFBQSxjQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxRQUFRLE9BQU8sQ0FBQyxFQUFFLFNBQVMsQ0FBQztBQUFBLGNBQ3JFLGVBQWUsRUFBRSxHQUFHLEtBQUssS0FBSyxZQUFZLEVBQUUsRUFBRTtBQUFBLGNBQzlDO0FBQUEsWUFDRjtBQUFBLFlBQ0E7QUFBQSxVQUNGO0FBQUEsVUFDQSxFQUFFLFFBQVEsQ0FBQyxXQUFXLEdBQUcsU0FBUyxDQUFDLEVBQUUsRUFBRTtBQUFBLFFBQ3pDLEVBQUUsQ0FBQztBQUFBLE1BQ0w7QUFFTyxNQUFNLFdBQVcsQ0FBQyxTQUF5QixlQUFtQztBQUNuRixjQUFNLFNBQVMsUUFBUTtBQUN2QixjQUFNLGFBQWEsT0FBTyxDQUFDLEVBQUU7QUFDN0IsY0FBTSxZQUFZLE9BQU8sQ0FBQyxFQUFFO0FBQzVCLGNBQU0sZUFBZSxPQUFPLENBQUMsRUFBRTtBQUMvQixjQUFNLGVBQWUsYUFBYSxhQUFhLFNBQVMsQ0FBQztBQUN6RCxjQUFNLFlBQVksVUFBVSxnQkFBZ0IsY0FBYyxhQUFhLFNBQVMsQ0FBQztBQUNqRixjQUFNLFlBQVksVUFBVSxrQkFBa0IsWUFBWSxXQUFXLFlBQVksWUFBWTtBQUM3RixjQUFNLGFBQWEsVUFBVSxnQkFBZ0IsWUFBWSxXQUFXLFNBQVM7QUFDN0UsY0FBTSxtQkFBbUIsVUFBVSxrQkFBa0IsWUFBWSxXQUFXLFNBQVM7QUFDckYsY0FBTSxvQkFBb0IsWUFBWTtBQUN0QyxjQUFNLHFCQUFxQixJQUFJLE1BQU0sWUFBWTtBQUNqRCxZQUFJLGlCQUFpQjtBQUNyQixpQkFBUyxJQUFJLEdBQUcsSUFBSSxjQUFjLEVBQUUsR0FBRztBQUNyQyw2QkFBbUIsZUFBZSxJQUFJLENBQUMsSUFBSTtBQUMzQyw0QkFBa0IsV0FBVyxXQUFXLFlBQVksZUFBZSxJQUFJLENBQUM7QUFBQSxRQUMxRTtBQUVBLGNBQU0sb0JBQW9CO0FBQUEsVUFDeEI7QUFBQSxVQUNBLE9BQU8sQ0FBQztBQUFBLFVBQ1I7QUFBQSxVQUNBLFdBQVc7QUFBQSxVQUNYO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFFQSxjQUFNLHVCQUF1QixXQUFXLFlBQVk7QUFDcEQsWUFBSSx1QkFBdUIsV0FBVyxRQUFRO0FBQzVDLGdCQUFNLElBQUksTUFBTSx3RUFBd0U7QUFBQSxRQUMxRjtBQUVBLGNBQU0sY0FBYyxhQUFhLE1BQU0sR0FBRyxFQUFFLEVBQUUsT0FBTyxXQUFXLE1BQU0sb0JBQW9CLENBQUM7QUFDM0YsY0FBTSxhQUFhLFVBQVUsS0FBSyxXQUFXO0FBRTdDLGNBQU0sa0JBQW9DO0FBQUEsVUFDeEMsRUFBRSx1QkFBdUIsTUFBTSxXQUFXO0FBQUEsVUFDMUMsRUFBRSx1QkFBdUIsTUFBTSxVQUFVO0FBQUEsVUFDekMsR0FBRywyQkFBMkIsT0FBTyxDQUFDLEVBQUUsTUFBTSxrQkFBa0IsTUFBTSxXQUFXO0FBQUEsUUFDbkY7QUFFQSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxnQkFBTSxRQUFRLGNBQWMsUUFBUSxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLEtBQUssTUFBTTtBQUM3RSxnQkFBTSxVQUFVLGNBQWMsa0NBQWtDLGtCQUFrQixLQUFLLE1BQU07QUFFN0YsZ0JBQU0sU0FBUyxlQUFlLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxZQUFZLE1BQU07QUFDOUUsaUJBQU87QUFBQSxZQUNDLGFBQ0MsZ0JBQWdCLGVBQWUsS0FBSyxFQUNwQyxnQkFBZ0IsY0FBYyxLQUFLLEVBQ25DLGlCQUFpQixPQUFPLFNBQVMsTUFBTSxDQUFDO0FBQUEsY0FDdkMsYUFBYSxVQUFVLENBQUM7QUFBQSxjQUN4QixhQUFhLHNDQUFzQyxzQkFBc0IsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBLFFBSXRGO0FBQ0EsZ0JBQVE7QUFBQSxVQUNOO0FBQUEsWUFDRSxNQUFNO0FBQUEsWUFDTixhQUFhLEVBQUUsTUFBTSxXQUFXLFVBQVUsbUJBQW1CLENBQUMsUUFBUSxNQUFNLEVBQUU7QUFBQSxZQUM5RSxZQUFZLE9BQU87QUFBQSxjQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxVQUFVLENBQUM7QUFBQSxjQUNwRCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsZ0JBQUssYUFBYTtBQUFBO0FBQUEsY0FBdUIsRUFBRTtBQUFBLGNBQ3BFO0FBQUEsWUFDRjtBQUFBLFlBQ0E7QUFBQSxVQUNGO0FBQUEsVUFDQSxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxpQkFBaUIsRUFBRTtBQUFBLFFBQzNDO0FBQUEsTUFDRjtBQUVPLE1BQU0sMEJBQTBCLENBQUMsZUFBNEQ7QUFDbEcsY0FBTSxZQUFZLFdBQVc7QUFDN0IsZUFBTztBQUFBLFVBQ0w7QUFBQSxVQUNBLFVBQVU7QUFBQSxRQUNaO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQ2xMQSxNQXdCYUMsa0JBeUNQLHVDQXFITyxzQkFNQTtBQTVMYjtBQUFBO0FBQUE7QUFHQTtBQUVBO0FBQ0E7QUFHQTtBQWVPLE1BQU1BLG1CQUFpQixDQUFDLFFBQStCLGVBQXFEO0FBQ2pILFlBQUksT0FBTyxTQUFTLEtBQUssT0FBTyxTQUFTLEdBQUc7QUFDMUMsZ0JBQU0sSUFBSSxNQUFNLDhDQUE4QztBQUFBLFFBQ2hFO0FBQ0EsY0FBTSxlQUFlLFVBQVUsY0FBYyxXQUFXLGNBQWMsT0FBTyxDQUFDLEVBQUUsS0FBSyxNQUFNO0FBQzNGLGNBQU0sWUFBWSxXQUFXO0FBQzdCLGNBQU0sT0FBTyxPQUFPLENBQUM7QUFDckIsY0FBTSxTQUFTLE9BQU8sQ0FBQztBQUN2QixjQUFNLFlBQVksT0FBTyxXQUFXLElBQUksT0FBTyxDQUFDLElBQUk7QUFDcEQsWUFDRSxPQUFPLEtBQUssV0FBVyxLQUFLLEtBQUssVUFDakMsQ0FBQyxLQUFLLEtBQ0gsSUFBSSxDQUFDLEdBQUcsTUFBTyxNQUFNLGVBQWUsS0FBSyxLQUFLLElBQUksU0FBUyxNQUFNLE9BQU8sS0FBSyxDQUFDLElBQUksTUFBTSxPQUFPLEtBQUssQ0FBQyxDQUFFLEVBQ3ZHLE9BQU8sQ0FBQyxHQUFHLE1BQU0sS0FBSyxHQUFHLElBQUksR0FDaEM7QUFDQSxnQkFBTSxJQUFJO0FBQUEsWUFDUjtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBUUEsWUFBSSxXQUFXO0FBQ2IsY0FBSSxVQUFVLGFBQWEsS0FBSyxVQUFVO0FBQ3hDLGtCQUFNLElBQUksTUFBTSw4REFBOEQ7QUFBQSxVQUNoRjtBQUNBLGNBQ0UsVUFBVSxLQUFLLFdBQVcsT0FBTyxLQUFLLFVBQ3RDLENBQUMsVUFBVSxLQUFLLElBQUksQ0FBQyxHQUFHLE1BQU0sTUFBTSxPQUFPLEtBQUssQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLEdBQUcsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUNqRjtBQUNBLGtCQUFNLElBQUk7QUFBQSxjQUNSO0FBQUEsWUFDRjtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVBLE1BQU0sd0NBQXdDLENBQzVDLFFBQ0EsZUFDZ0I7QUFDaEIsY0FBTSxhQUFhLE9BQU8sQ0FBQyxFQUFFO0FBQzdCLGNBQU0sZUFBZSxPQUFPLENBQUMsRUFBRTtBQUMvQixjQUFNLFlBQVksV0FBVztBQUM3QixjQUFNLGFBQWEsVUFBVSxjQUFjLFdBQVcsWUFBWSxTQUFTO0FBQzNFLGNBQU0sZUFBZSxVQUFVLGNBQWMsV0FBVyxjQUFjLFNBQVM7QUFDL0UsY0FBTSxjQUFjLFdBQVcsTUFBTSxDQUFDO0FBQ3RDLG9CQUFZLE9BQU8sWUFBWSxHQUFHLEdBQUcsWUFBWTtBQUNqRCxjQUFNLGFBQWEsVUFBVSxLQUFLLFdBQVc7QUFDN0MsY0FBTSxhQUFhLE9BQU8sQ0FBQyxFQUFFO0FBQzdCLGNBQU0sWUFBWSxPQUFPLENBQUMsRUFBRTtBQUM1QixjQUFNLFdBQVc7QUFDakIsY0FBTSxrQkFBb0M7QUFBQSxVQUN4QyxFQUFFLHVCQUF1QixNQUFNLFdBQVc7QUFBQSxVQUMxQyxFQUFFLHVCQUF1QixNQUFNLGFBQWE7QUFBQSxVQUM1QyxFQUFFLHVCQUF1QixNQUFNLFdBQVc7QUFBQSxVQUMxQyxFQUFFLHVCQUF1QixNQUFNLFdBQVcsVUFBVTtBQUFBLFVBQ3BELEdBQUcsMkJBQTJCLEdBQUcsT0FBTyxJQUFJLENBQUMsT0FBTyxNQUFNLE1BQU0sSUFBSSxHQUFHLFdBQVc7QUFBQSxRQUNwRjtBQUVBLGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQ3RELGdCQUFNLE9BQU8sY0FBYyxRQUFRLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxDQUFDLEVBQUUsS0FBSyxNQUFNO0FBQzVFLGdCQUFNLFVBQVUsY0FBYyxnQkFBZ0IsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU07QUFDdkYsZ0JBQU0sU0FBUyxjQUFjLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU07QUFDaEYsZ0JBQU0sWUFDSixPQUFPLFNBQVMsSUFBSSxjQUFjLGFBQWEsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU0sSUFBSTtBQUM5RixnQkFBTSxTQUFTLGVBQWUsVUFBVSxZQUFZLFlBQVksTUFBTTtBQUN0RSxnQkFBTSxpQkFBaUIsQ0FBQyxNQUFNLFNBQVMsTUFBTTtBQUM3QyxjQUFJLFdBQVc7QUFDYiwyQkFBZSxLQUFLLFNBQVM7QUFBQSxVQUMvQjtBQUNBLGdCQUFNLFdBQThCO0FBQUEsWUFDbEMsRUFBRSxNQUFNLGVBQWUsTUFBTSxNQUFNO0FBQUEsWUFDbkMsRUFBRSxNQUFNLGlCQUFpQixNQUFNLE1BQU07QUFBQSxZQUNyQyxFQUFFLE1BQU0sZUFBZSxNQUFNLE1BQU07QUFBQSxZQUNuQyxFQUFFLE1BQU0sY0FBYyxNQUFNLE1BQU07QUFBQSxVQUNwQztBQUNBLGlCQUFPO0FBQUEsVUFDRCxhQUFhLGlCQUFpQixRQUFRLEVBQUUsaUJBQWlCLEdBQUcsZ0JBQWdCLE1BQU0sQ0FBQztBQUFBLFVBQ25GLGFBQWEsVUFBVSxDQUFDO0FBQUEsK0JBQ0gsT0FBTyxnQkFBZ0IsWUFBWSxDQUFDO0FBQUEsZ0NBQ25DLFFBQVEsS0FBSyxPQUFPO0FBQUEsV0FDekMsTUFBTTtBQUNQLGdCQUFJLGFBQWEsU0FBUyxHQUFHO0FBQzNCLHFCQUFPO0FBQUEscUNBQ2tCLGFBQWEsTUFBTTtBQUFBLDBCQUM5QixPQUFPLFdBQVcsa0JBQWtCLDBCQUEwQixDQUFDO0FBQUEsY0FDM0UsUUFBUSxXQUFXLG1CQUFtQixLQUFLLE9BQU8sQ0FBQztBQUFBO0FBQUEsWUFFdkQsT0FBTztBQUNMLHFCQUFPLHFCQUFxQixPQUFPLFdBQVcsa0JBQWtCLHNCQUFzQixDQUFDO0FBQUEsWUFDekY7QUFBQSxVQUNGLEdBQUcsQ0FBQztBQUFBLDZCQUNpQixLQUFLLEtBQUssT0FBTztBQUFBO0FBQUEsd0JBRXRCLE9BQU8sV0FBVyxrQkFBa0IsR0FBRyxDQUFDO0FBQUEsWUFDcEQsS0FBSyxXQUFXLGdCQUFnQixLQUFLLE9BQU8sQ0FBQztBQUFBO0FBQUEsbUNBRXRCLFFBQVEsYUFBYSxpQkFBaUIsQ0FBQztBQUFBO0FBQUEsa0NBRXhDLFdBQVcsVUFBVSxDQUFDO0FBQUE7QUFBQSxVQUU5QyxLQUFLLFdBQVcsZ0JBQWdCLHdCQUF3Qix5QkFBeUIsQ0FBQztBQUFBLHFEQUN2QyxZQUFZLE1BQU07QUFBQSx3QkFDL0MsT0FBTyxXQUFXLGtCQUFrQixPQUFPLGFBQWEsTUFBTSxNQUFNLENBQUM7QUFBQSxZQUNqRixLQUFLLFdBQVcsZ0JBQWdCLEtBQUssT0FBTyxDQUFDO0FBQUE7QUFBQSw0QkFFN0IsS0FBSyxnQkFBZ0IsY0FBYyxDQUFDO0FBQUE7QUFBQTtBQUFBLDJDQUdyQixLQUFLLFlBQVksaUJBQWlCLENBQUM7QUFBQTtBQUFBLG1DQUUzQyxXQUFXLGVBQWUsWUFBWTtBQUFBO0FBQUE7QUFBQSxvQ0FHckMsT0FBTyxXQUFXLGdCQUFnQix3QkFBd0IsQ0FBQztBQUFBLFVBQ3JGLE9BQU8sV0FBVyxpQkFBaUIsMEJBQTBCLHFCQUFxQixDQUFDO0FBQUEsc0JBQ3ZFLE9BQU8sYUFBYSxlQUFlLENBQUM7QUFBQSxXQUMvQyxNQUFNO0FBQ1AsZ0JBQUksQ0FBQyxXQUFXO0FBQ2QscUJBQU87QUFBQSxZQUNULE9BQU87QUFDTCxxQkFBTztBQUFBO0FBQUEsd0NBRXFCLFVBQVUsZ0JBQWdCLG9CQUFvQixDQUFDO0FBQUE7QUFBQSw4Q0FFekMsVUFBVSxZQUFZLHVCQUF1QixDQUFDO0FBQUE7QUFBQSxxQ0FFdkQsV0FBVyxlQUFlLFlBQVk7QUFBQTtBQUFBLFlBRWpFO0FBQUEsVUFDRixHQUFHLENBQUM7QUFBQSxpQ0FDcUIsMEJBQTBCLFVBQVUsQ0FBQztBQUFBLFVBQzVELE9BQU8sWUFBWSxjQUFjLGtCQUFrQixDQUFDO0FBQUE7QUFBQSxRQUU1RDtBQUNBLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWE7QUFBQSxZQUNYLE1BQU0sR0FBRyxXQUFXLFFBQVEsSUFBSSxPQUM3QixPQUFPLENBQUMsR0FBRyxNQUFNLE1BQU0sQ0FBQyxFQUN4QixJQUFJLENBQUMsVUFBVSxNQUFNLEtBQUssS0FBSyxHQUFHLENBQUMsRUFDbkMsS0FBSyxHQUFHLENBQUM7QUFBQSxZQUNaLG1CQUFtQixNQUFNLEtBQUssRUFBRSxRQUFRLE9BQU8sT0FBTyxHQUFHLENBQUMsSUFBSSxPQUFPLE1BQU07QUFBQSxVQUM3RTtBQUFBLFVBQ0EsWUFBWSxPQUFPO0FBQUEsWUFDakIsU0FBUyxDQUFDLEVBQUUsTUFBTSxhQUFhLFVBQVUsV0FBVyxDQUFDO0FBQUEsWUFDckQsZUFBZSxFQUFFLEdBQUcsS0FBSztBQUFBLGNBQUssYUFBYTtBQUFBO0FBQUEsWUFBdUIsRUFBRTtBQUFBLFlBQ3BFO0FBQUEsVUFDRjtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sdUJBQXVCLENBQUMsU0FBeUIsZUFBcUQ7QUFDakgsY0FBTSxTQUFTLFFBQVE7QUFDdkIsUUFBQUEsaUJBQWUsUUFBUSxVQUFVO0FBQ2pDLGdCQUFRLFFBQVEsc0NBQXNDLFFBQVEsUUFBUSxVQUFVLENBQUM7QUFBQSxNQUNuRjtBQUVPLE1BQU0sc0NBQXNDLENBQ2pELGVBRUEsNEJBQTRCO0FBQUEsUUFDMUIsV0FBVyxXQUFXO0FBQUEsUUFDdEIsWUFBWSxXQUFXO0FBQUEsUUFDdkIsY0FBYyxXQUFXO0FBQUEsTUFDM0IsQ0FBQztBQUFBO0FBQUE7OztBQ25NSCxNQWVNQyxrQkFlQSxpQ0FpRU8sK0JBR0E7QUFsR2I7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUNBO0FBR0E7QUFNQSxNQUFNQSxtQkFBaUIsQ0FBQyxXQUF3QztBQUM5RCxZQUFJLENBQUMsVUFBVSxPQUFPLFdBQVcsR0FBRztBQUNsQyxnQkFBTSxJQUFJLE1BQU0sbUNBQW1DO0FBQUEsUUFDckQ7QUFFQSxZQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssU0FBUyxHQUFHO0FBQzdCLGdCQUFNLElBQUksTUFBTSwyREFBMkQ7QUFBQSxRQUM3RTtBQUVBLFlBQUksT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLE9BQU8sQ0FBQyxFQUFFLEtBQUssUUFBUTtBQUNuRCxnQkFBTSxJQUFJLE1BQU07QUFBQSw0REFDd0M7QUFBQSxRQUMxRDtBQUFBLE1BQ0Y7QUFFQSxNQUFNLGtDQUFrQyxDQUN0QyxRQUNBLGVBQ2dCO0FBQ2hCLGNBQU0sYUFBYSxPQUFPLENBQUMsRUFBRTtBQUM3QixjQUFNLHNCQUFzQixPQUFPLENBQUMsRUFBRTtBQUN0QyxjQUFNLFlBQVksV0FBVztBQUU3QixjQUFNLGVBQWUsT0FBTyxDQUFDLEVBQUU7QUFDL0IsY0FBTSxrQkFBa0IsT0FBTyxDQUFDLEVBQUU7QUFDbEMsY0FBTSxPQUFPLFVBQVUsY0FBYyxXQUFXLE1BQU0sU0FBUztBQUMvRCxjQUFNLGVBQWUsV0FBVyxJQUFJO0FBRXBDLGNBQU0sY0FBYyxhQUFhLE1BQU0sQ0FBQztBQUN4QyxjQUFNLGFBQWEsVUFBVSxLQUFLLFdBQVc7QUFFN0MsY0FBTSxRQUFRLGNBQWMsU0FBUyxxQkFBcUIsU0FBUztBQUNuRSxjQUFNLFVBQVUsY0FBYyxnQkFBZ0IsaUJBQWlCLGFBQWEsTUFBTTtBQUNsRixjQUFNLFNBQVMsZUFBZSxVQUFVLHFCQUFxQixZQUFZLE1BQU07QUFFL0UsY0FBTSxrQkFBb0M7QUFBQSxVQUN4QyxFQUFFLHVCQUF1QixNQUFNLFdBQVc7QUFBQSxVQUMxQyxFQUFFLHFCQUFzQixNQUFNLGFBQWE7QUFBQSxVQUMzQyxFQUFFLHVCQUF1QixNQUFNLEtBQUs7QUFBQSxRQUN0QztBQUNBLHdCQUFnQixLQUFLLEdBQUcsMkJBQTJCLFlBQVksY0FBYyxXQUFXLENBQUM7QUFDekYsY0FBTSxvQkFBd0QsQ0FBQyxRQUFRLE1BQU07QUFLN0UsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFBQSxRQUNsRCxhQUNDLGdCQUFnQixjQUFjLEtBQUssRUFDbkMsZ0JBQWdCLGdCQUFnQixLQUFLLEVBQ3JDLGdCQUFnQixRQUFRLEtBQUssRUFDN0IsaUJBQWlCLE9BQU8sU0FBUyxNQUFNLENBQUM7QUFBQSxRQUN6QyxhQUFhLFVBQVUsQ0FBQztBQUFBLFFBQ3hCLGFBQWEsc0NBQXNDLHFCQUFxQixDQUFDO0FBQUE7QUFBQSw0QkFFckQsT0FBTyxnQkFBZ0IsWUFBWSxDQUFDO0FBQUE7QUFBQSxrQkFFOUMsUUFBUSxZQUFZLFlBQVksQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBLDJCQUl4QixNQUFNLEtBQUssT0FBTztBQUFBLFFBQ3JDLE1BQU0sV0FBVyxnQkFBZ0IsaUJBQWlCLFVBQVUsQ0FBQztBQUFBLG9CQUNqRCxNQUFNLGFBQWEsY0FBYyxDQUFDO0FBQUE7QUFBQSxRQUU5QyxPQUFPLFlBQVksY0FBYyxPQUFPLENBQUM7QUFBQTtBQUcvQyxlQUFPO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixhQUFhLEVBQUUsa0JBQWtCO0FBQUEsVUFDakMsWUFBWSxPQUFPO0FBQUEsWUFDakIsU0FBUyxDQUFDLEVBQUUsTUFBTSxhQUFhLFVBQVUsT0FBTyxDQUFDLEVBQUUsU0FBUyxDQUFDO0FBQUEsWUFDN0QsZUFBZSxFQUFFLEdBQUcsS0FBSztBQUFBLGNBQUssYUFBYTtBQUFBO0FBQUEsWUFBdUIsRUFBRTtBQUFBLFlBQ3BFO0FBQUEsVUFDRjtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sZ0NBQWdDLENBQUMsZUFDNUMsNEJBQTRCLEVBQUUsTUFBTSxXQUFXLEtBQWUsQ0FBQztBQUUxRCxNQUFNLGlCQUFpQixDQUFDLFNBQXlCLGVBQStDO0FBQ3JHLGNBQU0sU0FBUyxRQUFRO0FBQ3ZCLFFBQUFBLGlCQUFlLE1BQU07QUFDckIsZ0JBQVEsUUFBUSxnQ0FBZ0MsUUFBUSxRQUFRLFVBQVUsQ0FBQztBQUFBLE1BQzdFO0FBQUE7QUFBQTs7O0FDdEdBLE1Ba0JNQyxrQkF5QkEsdUJBb1FPLHFCQWNBO0FBN1RiO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFJQTtBQVNBLE1BQU1BLG1CQUFpQixDQUFDLFdBQXdDO0FBQzlELFlBQUksQ0FBQyxRQUFRO0FBQ1gsZ0JBQU0sSUFBSSxNQUFNLGtCQUFrQjtBQUFBLFFBQ3BDO0FBQ0EsWUFBSSxPQUFPLFNBQVMsS0FBSyxPQUFPLFNBQVMsR0FBRztBQUMxQyxnQkFBTSxJQUFJLE1BQU0sc0JBQXNCO0FBQUEsUUFDeEM7QUFHQSxZQUFJLE9BQU8sV0FBVyxLQUFLLE9BQU8sQ0FBQyxFQUFFLEtBQUssU0FBUyxHQUFHO0FBQ3BELGdCQUFNLElBQUksTUFBTSwwQkFBMEI7QUFBQSxRQUM1QztBQUVBLFlBQUksT0FBTyxDQUFDLEVBQUUsYUFBYSxPQUFPLENBQUMsRUFBRSxZQUFhLE9BQU8sV0FBVyxLQUFLLE9BQU8sQ0FBQyxFQUFFLGFBQWEsT0FBTyxDQUFDLEVBQUUsVUFBVztBQUNuSCxnQkFBTSxJQUFJLE1BQU0sNEJBQTRCO0FBQUEsUUFDOUM7QUFBQSxNQUNGO0FBU0EsTUFBTSx3QkFBd0IsQ0FBQyxRQUErQixlQUE0QztBQUN4RyxjQUFNLFNBQVMsT0FBTyxDQUFDLEVBQUUsS0FBSyxNQUFNO0FBQ3BDLGNBQU0sU0FBUyxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU07QUFDcEMsY0FBTSxDQUFDLEdBQUcsR0FBRyxDQUFDLElBQUksU0FBUztBQUFBLFVBQ3pCO0FBQUEsVUFDQSxXQUFXO0FBQUEsVUFDWDtBQUFBLFVBQ0EsV0FBVztBQUFBLFVBQ1gsT0FBTyxXQUFXLElBQUksT0FBTyxDQUFDLEVBQUUsT0FBTztBQUFBLFFBQ3pDO0FBQ0EsY0FBTSxjQUFjLENBQUMsR0FBRyxDQUFDO0FBQ3pCLFlBQUksQ0FBQyxhQUFhO0FBQ2hCLGdCQUFNLElBQUksTUFBTSxxQ0FBcUM7QUFBQSxRQUN2RDtBQUNBLGNBQU0sV0FBVztBQUNqQixjQUFNLFdBQVcsS0FBSyxLQUFLLElBQUksUUFBUTtBQUN2QyxjQUFNLFdBQVcsS0FBSyxLQUFLLElBQUksUUFBUTtBQUV2QyxjQUFNLFlBQVk7QUFFbEIsY0FBTSxhQUFhLFVBQVUsS0FBSyxXQUFXO0FBQzdDLGNBQU0sa0JBQW9DO0FBQUEsVUFDeEMsRUFBRSx1QkFBdUIsTUFBTSxZQUFZLFdBQVcsV0FBVztBQUFBLFVBQ2pFLEVBQUUsdUJBQXVCLE1BQU0sRUFBRTtBQUFBLFVBQ2pDLEVBQUUsdUJBQXVCLE1BQU0sRUFBRTtBQUFBLFVBQ2pDLEVBQUUsdUJBQXVCLE1BQU0sRUFBRTtBQUFBLFVBQ2pDLEVBQUUscUJBQXNCLE1BQU0sV0FBVyxNQUFNO0FBQUEsVUFDL0MsRUFBRSxxQkFBc0IsTUFBTSxXQUFXLEtBQUs7QUFBQSxRQUNoRDtBQUNBLGNBQU0sb0JBQXdELENBQUMsUUFBUSxNQUFNO0FBQzdFLFlBQUksT0FBTyxXQUFXLEdBQUc7QUFDdkIsMEJBQWdCLEtBQUssR0FBRywyQkFBMkIsT0FBTyxDQUFDLEVBQUUsSUFBSSxDQUFDO0FBQ2xFLDRCQUFrQixLQUFLLE1BQU07QUFBQSxRQUMvQjtBQUNBLHdCQUFnQixLQUFLLEdBQUcsMkJBQTJCLFdBQVcsQ0FBQztBQUUvRCxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxjQUFJLE9BQU87QUFDWCxjQUFJLFdBQVcsVUFBVSxXQUFXLFFBQVE7QUFDMUMsbUJBQU87QUFBQSxVQUNULFdBQVcsV0FBVyxVQUFVLENBQUMsV0FBVyxRQUFRO0FBQ2xELG1CQUFPO0FBQUEsVUFDVCxXQUFXLENBQUMsV0FBVyxVQUFVLFdBQVcsUUFBUTtBQUNsRCxtQkFBTztBQUFBLFVBQ1QsV0FBVyxDQUFDLFdBQVcsVUFBVSxDQUFDLFdBQVcsUUFBUTtBQUNuRCxtQkFBTztBQUFBLFVBQ1Q7QUFFQSxnQkFBTSxpQkFBaUIsV0FBVyxVQUFVLElBQUksS0FBSztBQUNyRCxnQkFBTSxJQUFJLGNBQWMsS0FBSyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLElBQUk7QUFDL0QsZ0JBQU0sSUFBSSxjQUFjLEtBQUssT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxJQUFJO0FBQy9ELGdCQUFNLFdBQVcsRUFBRSxLQUFLO0FBQ3hCLGNBQUksSUFBMEI7QUFDOUIsZ0JBQU0sWUFBWSxDQUFDLEdBQUcsQ0FBQztBQUN2QixjQUFJLE9BQU8sV0FBVyxHQUFHO0FBQ3ZCLGdCQUFJLGNBQWMsS0FBSyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLEtBQUssTUFBTTtBQUNoRSxzQkFBVSxLQUFLLENBQUM7QUFBQSxVQUNsQjtBQUNBLGdCQUFNLFNBQVMsZUFBZSxVQUFVLE9BQU8sQ0FBQyxFQUFFLFVBQVUsWUFBWSxNQUFNO0FBQzlFLG9CQUFVLEtBQUssTUFBTTtBQUNyQixnQkFBTSxXQUE4QjtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxlQUFlLE1BQU0sTUFBTTtBQUFBLFlBQ25DLEVBQUUsTUFBTSxLQUFLLE1BQU0sTUFBTTtBQUFBLFlBQ3pCLEVBQUUsTUFBTSxLQUFLLE1BQU0sTUFBTTtBQUFBLFlBQ3pCLEVBQUUsTUFBTSxLQUFLLE1BQU0sTUFBTTtBQUFBLFlBQ3pCLEVBQUUsTUFBTSxTQUFTLE1BQU0sTUFBTTtBQUFBLFlBQzdCLEVBQUUsTUFBTSxRQUFRLE1BQU0sTUFBTTtBQUFBLFVBQzlCO0FBQ0EsaUJBQU87QUFBQSxJQUNQLGFBQWEsaUJBQWlCLFFBQVEsRUFBRSxpQkFBaUIsR0FBRyxTQUFTLENBQUM7QUFBQTtBQUFBLElBRXRFLGFBQWEsVUFBVSxDQUFDO0FBQUEsTUFDdEIsYUFBYSxzQ0FBc0Msc0JBQXNCLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUs5RCxRQUFRO0FBQUE7QUFBQSxRQUVsQixJQUFJO0FBQUE7QUFBQTtBQUFBLE1BR04sY0FBYztBQUFBLE9BQ2IsTUFBTTtBQUNQLGdCQUFJLEtBQUssTUFBTTtBQUNiLHFCQUFPLGlCQUFpQixFQUFFLDJCQUEyQixjQUFjLE1BQU0sQ0FBQyxjQUN4RSxRQUNGLHFCQUFxQixFQUFFLFlBQVksU0FBUyxDQUFDO0FBQUEsWUFDL0M7QUFDQSxtQkFBTztBQUFBLFVBQ1QsR0FBRyxDQUFDO0FBQUE7QUFBQTtBQUFBLFFBR047QUFFQSxjQUFNLHdCQUF3QixDQUFDLGlCQUErQjtBQUM1RCxnQkFBTSxJQUFJLGNBQWMsS0FBSyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLElBQUk7QUFDL0QsZ0JBQU0sSUFBSSxjQUFjLEtBQUssT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxJQUFJO0FBQy9ELGNBQUksSUFBMEI7QUFDOUIsZ0JBQU0sWUFBWSxDQUFDLEdBQUcsQ0FBQztBQUN2QixjQUFJLE9BQU8sV0FBVyxHQUFHO0FBQ3ZCLGdCQUFJLGNBQWMsS0FBSyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLEtBQUssTUFBTTtBQUNoRSxzQkFBVSxLQUFLLENBQUM7QUFBQSxVQUNsQjtBQUNBLGdCQUFNLFNBQVMsZUFBZSxVQUFVLE9BQU8sQ0FBQyxFQUFFLFVBQVUsWUFBWSxNQUFNO0FBQzlFLG9CQUFVLEtBQUssTUFBTTtBQUNyQixnQkFBTSxXQUE4QjtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxjQUFjLE1BQU0sTUFBTTtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxLQUFLLE1BQU0sTUFBTTtBQUFBLFlBQ3pCLEVBQUUsTUFBTSxLQUFLLE1BQU0sTUFBTTtBQUFBLFlBQ3pCLEVBQUUsTUFBTSxLQUFLLE1BQU0sTUFBTTtBQUFBLFlBQ3pCLEVBQUUsTUFBTSxTQUFTLE1BQU0sTUFBTTtBQUFBLFlBQzdCLEVBQUUsTUFBTSxRQUFRLE1BQU0sTUFBTTtBQUFBLFVBQzlCO0FBRUEsY0FBSSxhQUFhO0FBQ2pCLGNBQUksc0JBQXNCO0FBQzFCLGNBQUksV0FBVyxVQUFVLFdBQVcsUUFBUTtBQUMxQyxrQ0FBc0I7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsMkNBTWUsRUFBRSxLQUFLLEtBQUs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLDJDQVFaLEVBQUUsS0FBSyxLQUFLO0FBQUE7QUFBQTtBQUdqRCx5QkFBYTtBQUFBLFVBQ2YsV0FBVyxXQUFXLFVBQVUsQ0FBQyxXQUFXLFFBQVE7QUFDbEQsa0NBQXNCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLDJDQU1lLEVBQUUsS0FBSyxLQUFLO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSwyQ0FRWixFQUFFLEtBQUssS0FBSztBQUFBO0FBQUE7QUFHakQseUJBQWE7QUFBQSxVQUNmLFdBQVcsQ0FBQyxXQUFXLFVBQVUsV0FBVyxRQUFRO0FBQ2xELGtDQUFzQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSwyQ0FNZSxFQUFFLEtBQUssS0FBSztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsMkNBUVosRUFBRSxLQUFLLEtBQUs7QUFBQTtBQUFBO0FBR2pELHlCQUFhO0FBQUEsVUFDZixXQUFXLENBQUMsV0FBVyxVQUFVLENBQUMsV0FBVyxRQUFRO0FBQ25ELGtDQUFzQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSwyQ0FNZSxFQUFFLEtBQUssS0FBSztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsMkNBUVosRUFBRSxLQUFLLEtBQUs7QUFBQTtBQUFBO0FBR2pELHlCQUFhO0FBQUEsVUFDZjtBQUVBLGdCQUFNLGlCQUFpQixXQUFXLFVBQVUsSUFBSSxLQUFLO0FBRXJELGlCQUFPO0FBQUEsSUFDUCxhQUFhLGlCQUFpQixRQUFRLEVBQUUsaUJBQWlCLEdBQUcsU0FBUyxDQUFDO0FBQUEsdUNBQ25DLEVBQUUsS0FBSyxPQUFPLEtBQUssUUFBUSxNQUFNLFFBQVE7QUFBQSx1Q0FDekMsRUFBRSxLQUFLLE9BQU8sS0FBSyxRQUFRLE1BQU0sUUFBUTtBQUFBLElBQzVFLGFBQWEsVUFBVSxDQUFDLFVBQVUsVUFBVSxDQUFDLENBQUMsQ0FBQztBQUFBLHFFQUNrQixRQUFRO0FBQUEscUVBQ1IsUUFBUTtBQUFBLHlDQUNwQyxRQUFRO0FBQUE7QUFBQSxrQkFFL0IsT0FBTyxLQUFLLEtBQUs7QUFBQTtBQUFBLFFBRTNCLG1CQUFtQjtBQUFBLDRCQUNDLFFBQVE7QUFBQTtBQUFBO0FBQUEsa0NBR0YsUUFBUTtBQUFBLFVBQ2hDLFVBQVU7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE1BS2QsY0FBYztBQUFBO0FBQUE7QUFBQSxPQUdiLE1BQU07QUFDUCxnQkFBSSxLQUFLLE1BQU07QUFDYixxQkFBTyxpQkFBaUIsRUFBRSwyQkFBMkIsY0FBYyxNQUFNLENBQUMsY0FDeEUsT0FBTyxLQUFLLEtBQ2QscUJBQXFCLEVBQUUsWUFBWSxTQUFTLENBQUM7QUFBQSxZQUMvQztBQUNBLG1CQUFPO0FBQUEsVUFDVCxHQUFHLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBS047QUFFQSxZQUFJLFdBQVc7QUFDYixpQkFBTztBQUFBLFlBQ0wsTUFBTTtBQUFBLFlBQ04sYUFBYSxFQUFFLE1BQU0sR0FBRyxXQUFXLFFBQVEsSUFBSSxrQkFBa0I7QUFBQSxZQUNqRSxZQUFZLE9BQU87QUFBQSxjQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxPQUFPLENBQUMsRUFBRSxTQUFTLENBQUM7QUFBQSxjQUM3RCxlQUFlLEVBQUUsR0FBRyxXQUFXLFNBQVM7QUFBQSxjQUN4QztBQUFBLFlBQ0Y7QUFBQSxZQUNBLGlCQUFpQjtBQUFBLFVBQ25CO0FBQUEsUUFDRjtBQUVBLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWEsRUFBRSxNQUFNLEdBQUcsV0FBVyxRQUFRLElBQUksa0JBQWtCO0FBQUEsVUFDakUsWUFBWSxPQUFPO0FBQUEsWUFDakIsU0FBUyxDQUFDLEVBQUUsTUFBTSxhQUFhLFVBQVUsT0FBTyxDQUFDLEVBQUUsU0FBUyxDQUFDO0FBQUEsWUFDN0QsZUFBZSxFQUFFLEdBQUcsS0FBSztBQUFBLGNBQUssYUFBYTtBQUFBO0FBQUEsWUFBdUIsRUFBRTtBQUFBLFlBQ3BFO0FBQUEsVUFDRjtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sc0JBQXNCLENBQUMsZUFBd0Q7QUFDMUYsY0FBTSxTQUFTLFdBQVc7QUFDMUIsY0FBTSxTQUFTLFdBQVc7QUFDMUIsY0FBTSxRQUFRLFdBQVc7QUFDekIsY0FBTSxPQUFPLFdBQVc7QUFDeEIsZUFBTztBQUFBLFVBQ0w7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBLFVBQVUsR0FBRyxXQUFXLE1BQU0sSUFBSSxXQUFXLE1BQU0sSUFBSSxXQUFXLFVBQVUsQ0FBQztBQUFBLFFBQy9FO0FBQUEsTUFDRjtBQUVPLE1BQU0sT0FBTyxDQUFDLFNBQXlCLGVBQXFDO0FBQ2pGLFFBQUFBLGlCQUFlLFFBQVEsTUFBTTtBQUM3QixnQkFBUSxRQUFRLHNCQUFzQixRQUFRLFFBQVEsVUFBVSxDQUFDO0FBQUEsTUFDbkU7QUFBQTtBQUFBOzs7QUNoVUEsTUFXSyxNQUFNLE1BQU0sTUFBTSxNQVdqQkMsa0JBaUJBLGtCQWFBLHNCQWFBLGVBZ0JBLFdBaUNBLGFBcUNBLGNBNkNBLDZCQXlFTyxZQUtBO0FBbFJiO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFDQTtBQUdBO0FBRUEsTUFBSSxDQUFDLE1BQU0sTUFBTSxNQUFNLFFBQVEsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO0FBVzFDLE1BQU1BLG1CQUFpQixDQUFDLFdBQXdDO0FBQzlELFlBQUksT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLEdBQUc7QUFDL0IsZ0JBQU0sSUFBSSxNQUFNLCtCQUErQjtBQUFBLFFBQ2pEO0FBQ0EsWUFBSSxPQUFPLENBQUMsRUFBRSxLQUFLLFdBQVcsT0FBTyxDQUFDLEVBQUUsS0FBSyxRQUFRO0FBQ25ELGdCQUFNLElBQUksTUFBTSxtREFBbUQ7QUFBQSxRQUNyRTtBQUVBLFlBQUksT0FBTyxDQUFDLEVBQUUsS0FBSyxTQUFTLE1BQU0sT0FBTyxDQUFDLEVBQUUsS0FBSyxPQUFPLENBQUMsRUFBRSxLQUFLLFNBQVMsQ0FBQyxHQUFHO0FBQzNFLGdCQUFNLElBQUksTUFBTSwyQ0FBMkMsT0FBTyxDQUFDLEVBQUUsS0FBSyxTQUFTLENBQUMsRUFBRTtBQUFBLFFBQ3hGO0FBRUEsWUFBSSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsTUFBTSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRztBQUMzQyxnQkFBTSxJQUFJLE1BQU0sNkNBQTZDO0FBQUEsUUFDL0Q7QUFBQSxNQUNGO0FBRUEsTUFBTSxtQkFBbUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBYXpCLE1BQU0sdUJBQXVCLENBQUMsYUFBNkI7QUFBQSx3Q0FDbkIsUUFBUSx5QkFBeUIsUUFBUTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGtCQU8vRCxRQUFRO0FBQUE7QUFBQTtBQUFBO0FBSzFCLE1BQU0sZ0JBQWdCLENBQUMsZUFBNEM7QUFBQTtBQUFBLE1BRzdELFdBQVcsaUJBQWlCLElBQ3hCO0FBQUE7QUFBQTtBQUFBLFFBSUE7QUFBQTtBQUFBO0FBQUEsS0FJTjtBQUFBO0FBQUE7QUFJSixNQUFNLFlBQVksQ0FBQyxlQUE0QztBQUFBLElBRTNELFdBQVcsZ0JBQWdCLGVBQ3ZCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsV0EwQkEsRUFDTjtBQUFBO0FBR0YsTUFBTSxjQUFjLENBQUMsT0FBc0IsVUFBa0IsZUFDM0Q7QUFBQSxxR0FDbUcsUUFBUTtBQUFBLG1CQUMxRixRQUFRO0FBQUE7QUFBQSxlQUVaLElBQUk7QUFBQSxlQUNKLElBQUksa0JBQ2hCLE1BQU07QUFDTCxnQkFBUSxXQUFXLGFBQWE7QUFBQSxVQUM5QixLQUFLO0FBQ0gsbUJBQU87QUFBQTtBQUFBLHNCQUVPLElBQUk7QUFBQSxzQkFDSixJQUFJO0FBQUE7QUFBQSxxQkFFTCxRQUFRO0FBQUE7QUFBQTtBQUFBLFVBR3ZCLEtBQUs7QUFDSCxtQkFBTztBQUFBLG9CQUNLLElBQUk7QUFBQSxvQkFDSixJQUFJO0FBQUE7QUFBQSxVQUVsQixLQUFLO0FBQ0gsbUJBQU87QUFBQSxvQkFDSyxJQUFJO0FBQUEsb0JBQ0osSUFBSTtBQUFBO0FBQUEsVUFFbEI7QUFDRSxrQkFBTSxJQUFJLE1BQU0sZ0JBQWdCLFdBQVcsV0FBVyxtQkFBbUI7QUFBQSxRQUM3RTtBQUFBLE1BQ0YsR0FBRyxJQUNIO0FBQUEsYUFDVyxNQUFNLGFBQWEsU0FBUyxDQUFDO0FBQUE7QUFBQTtBQUkxQyxNQUFNLGVBQWUsQ0FBQyxRQUF1QixVQUFrQixnQkFDNUQsTUFBTTtBQUNMLGdCQUFRLFdBQVcsTUFBTTtBQUFBLFVBQ3ZCLEtBQUs7QUFDSCxtQkFBTztBQUFBLHlGQUMwRSxJQUFJLGNBQWMsSUFBSTtBQUFBO0FBQUEsVUFFekcsS0FBSztBQUNILG1CQUFPO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGdFQU1pRCxJQUFJLGNBQWMsSUFBSTtBQUFBLGdFQUN0QixJQUFJLGNBQWMsSUFBSTtBQUFBLGdFQUN0QixJQUFJLGNBQWMsSUFBSTtBQUFBLGdFQUN0QixJQUFJLGNBQWMsSUFBSTtBQUFBO0FBQUEsc0JBRWhFLFFBQVE7QUFBQSxzQkFDUixRQUFRO0FBQUEsc0JBQ1IsUUFBUTtBQUFBLHNCQUNSLFFBQVE7QUFBQTtBQUFBO0FBQUEsVUFHeEIsS0FBSztBQUNILG1CQUFPO0FBQUE7QUFBQTtBQUFBLDBCQUdXLFFBQVE7QUFBQTtBQUFBO0FBQUEsNEVBRzBDLElBQUksY0FBYyxJQUFJO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxVQVE1RjtBQUNFLGtCQUFNLElBQUksTUFBTSxRQUFRLFdBQVcsSUFBSSxtQkFBbUI7QUFBQSxRQUM5RDtBQUFBLE1BQ0YsR0FBRyxJQUFJLEdBQUcsT0FBTyxZQUFZLGNBQWMsUUFBUSxDQUFDO0FBRXRELE1BQU0sOEJBQThCLENBQUMsUUFBK0IsZUFBaUQ7QUFDbkgsY0FBTSxJQUFJLGNBQWMsS0FBSyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLEtBQUssTUFBTTtBQUV0RSxjQUFNLFlBQVksQ0FBQyxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUMxRSxjQUFNLE9BQU8sY0FBYyxRQUFRLE9BQU8sQ0FBQyxFQUFFLFVBQVUsVUFBVSxRQUFRLENBQUM7QUFDMUUsWUFBSSxjQUFjLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDN0YsWUFBSSxXQUFXLFdBQVcsUUFBUTtBQUNoQyx3QkFBYyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxHQUFHLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxHQUFHLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxHQUFHLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ3pGLFdBQUMsTUFBTSxNQUFNLE1BQU0sSUFBSSxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztBQUFBLFFBQ3hDO0FBQ0EsY0FBTSxTQUFTLGVBQWUsVUFBVSxPQUFPLENBQUMsRUFBRSxVQUFVLFlBQVksTUFBTTtBQUM5RSxjQUFNLFdBQVcsRUFBRSxLQUFLO0FBQ3hCLGNBQU0sYUFBYSxVQUFVLEtBQUssV0FBVztBQUU3QyxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEdBQUcsMkJBQTJCLE9BQU8sQ0FBQyxFQUFFLE1BQU0sV0FBVyxXQUFXO0FBQUEsUUFDdEU7QUFFQSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUFBLElBQ3RELGFBQWEsZ0JBQWdCLGVBQWUsS0FBSyxFQUFFLGlCQUFpQixHQUFHLE1BQU0sTUFBTSxDQUFDO0FBQUEsSUFDcEYsZ0JBQWdCO0FBQUEsSUFDaEIscUJBQXFCLFFBQVEsQ0FBQztBQUFBLElBQzlCLGNBQWMsVUFBVSxDQUFDO0FBQUEsSUFDekIsVUFBVSxVQUFVLENBQUM7QUFBQSxJQUNyQixZQUFZLEdBQUcsVUFBVSxVQUFVLENBQUM7QUFBQTtBQUFBLElBRXBDLGFBQWEsVUFBVSxDQUFDO0FBQUEsTUFDdEIsYUFBYSxzQ0FBc0Msc0JBQXNCLENBQUM7QUFBQSx3Q0FDeEMsSUFBSTtBQUFBLHdDQUNKLElBQUk7QUFBQTtBQUFBLFFBR3BDLFdBQVcsaUJBQWlCLElBQ3hCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxVQU1BO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxPQU1OO0FBQUE7QUFBQTtBQUFBLHNCQUdnQixPQUFPLGdCQUFnQixZQUFZLENBQUM7QUFBQSw2Q0FDYixJQUFJLGNBQWMsSUFBSSxjQUFjLElBQUk7QUFBQSxrQkFDbkUsS0FBSyxhQUFhLGNBQWMsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBLFFBSTNDLGFBQWEsUUFBUSxVQUFVLFVBQVUsQ0FBQztBQUFBO0FBR2hELGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWEsRUFBRSxNQUFNLEdBQUcsV0FBVyxRQUFRLElBQUksbUJBQW1CLENBQUMsUUFBUSxNQUFNLEVBQUU7QUFBQSxVQUNuRixZQUFZLENBQUNDLFlBQVc7QUFDdEIsa0JBQU1DLGNBQWEsVUFBVSxLQUFLLFdBQVc7QUFDN0MsbUJBQU87QUFBQSxjQUNMLFNBQVMsQ0FBQyxFQUFFLE1BQU0sYUFBYSxVQUFVRCxRQUFPLENBQUMsRUFBRSxTQUFTLENBQUM7QUFBQSxjQUM3RCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsZ0JBQUtDLGNBQWE7QUFBQTtBQUFBLGNBQXVCLEVBQUU7QUFBQSxjQUNwRTtBQUFBLFlBQ0Y7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxhQUFhLENBQUMsU0FBeUIsZUFBMEM7QUFDNUYsUUFBQUYsaUJBQWUsUUFBUSxNQUFNO0FBQzdCLGdCQUFRLFFBQVEsNEJBQTRCLFFBQVEsUUFBUSxVQUFVLENBQUM7QUFBQSxNQUN6RTtBQUVPLE1BQU0sNEJBQTRCLENBQUMsZUFDeEMsNEJBQTRCO0FBQUEsUUFDMUIsY0FBYyxXQUFXO0FBQUEsUUFDekIsTUFBTSxXQUFXO0FBQUEsUUFDakIsYUFBYSxXQUFXO0FBQUEsUUFDeEIsUUFBUSxXQUFXO0FBQUEsTUFDckIsQ0FBQztBQUFBO0FBQUE7OztBQ3hSSCxNQW1CTSxVQUdBRyxrQkFvUE8sbUNBR1BDLDJCQUVBLGtCQW9ETyxnQ0FpREE7QUFwWGI7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQU9BO0FBQ0E7QUFFQSxNQUFNLFdBQVcsQ0FBQyxRQUErQixNQUMvQyxPQUFPLFNBQVMsS0FBSyxPQUFPLENBQUMsRUFBRSxLQUFLLFNBQVMsSUFBSSxPQUFPLENBQUMsSUFBSTtBQUUvRCxNQUFNRCxtQkFBaUIsQ0FBQyxRQUErQixlQUFvRDtBQUN6RyxjQUFNLFFBQVEsT0FBTyxDQUFDO0FBQ3RCLGNBQU0sTUFBTSxTQUFTLFFBQVEsQ0FBQztBQUM5QixjQUFNLFFBQVEsU0FBUyxRQUFRLENBQUM7QUFDaEMsY0FBTSxPQUFPLFNBQVMsUUFBUSxDQUFDO0FBQy9CLGNBQU0saUJBQWlCLFNBQVMsUUFBUSxDQUFDO0FBQ3pDLGNBQU0sZ0JBQWdCLFNBQVMsUUFBUSxDQUFDO0FBQ3hDLGNBQU0sVUFBVSxTQUFTLFFBQVEsQ0FBQztBQUNsQyxjQUFNLFlBQVksU0FBUyxRQUFRLENBQUM7QUE2Q3BDLFlBQUksTUFBTSxLQUFLLFdBQVcsS0FBSyxNQUFNLEtBQUssV0FBVyxHQUFHO0FBQ3RELGdCQUFNLElBQUksTUFBTSxtREFBbUQ7QUFBQSxRQUNyRTtBQUVBLGNBQU0sWUFBWSxNQUFNLEtBQUssQ0FBQztBQUM5QixjQUFNLGlCQUFpQixNQUFNLEtBQUssQ0FBQztBQUNuQyxjQUFNLGFBQWEsTUFBTSxLQUFLLFdBQVcsSUFBSSxNQUFNLEtBQUssQ0FBQyxJQUFJLFdBQVcsV0FBVyxNQUFNLEtBQUssQ0FBQztBQUMvRixZQUFJLG1CQUFtQjtBQUV2QixZQUFJLHFCQUFxQjtBQUN6QixZQUFJLG9CQUFvQjtBQUN4QixjQUFNLFdBQVcsS0FBSyxNQUFNLGFBQWEsV0FBVyxRQUFRO0FBQzVELFlBQUksV0FBVyxhQUFhLFVBQVUsS0FBSyxRQUFRLElBQUksS0FBSyxVQUFVLEtBQUssVUFBVSxJQUFJLEdBQUc7QUFDMUYsY0FBSSxRQUFRLEtBQUssV0FBVyxHQUFHO0FBQzdCLGtCQUFNLElBQUksTUFBTSxtREFBbUQ7QUFBQSxVQUNyRTtBQUNBLGNBQUksUUFBUSxLQUFLLENBQUMsTUFBTSxhQUFhLFFBQVEsS0FBSyxDQUFDLE1BQU0sV0FBVyxZQUFZLFFBQVEsS0FBSyxDQUFDLE1BQU0sVUFBVTtBQUM1RyxrQkFBTSxJQUFJLE1BQU0saUZBQWlGO0FBQUEsVUFDbkc7QUFDQSxjQUNFLFVBQVUsS0FBSyxDQUFDLE1BQU0sYUFDdEIsVUFBVSxLQUFLLENBQUMsTUFBTSxXQUFXLFlBQ2pDLFVBQVUsS0FBSyxDQUFDLE1BQU0sVUFDdEI7QUFDQSxrQkFBTSxJQUFJLE1BQU0sbUZBQW1GO0FBQUEsVUFDckc7QUFDQSxjQUFJLFFBQVEsS0FBSyxDQUFDLE1BQU0sVUFBVSxLQUFLLENBQUMsR0FBRztBQUN6QyxrQkFBTSxJQUFJLE1BQU0sZ0ZBQWdGO0FBQUEsVUFDbEc7QUFDQSxjQUFJLFVBQVUsS0FBSyxXQUFXLEdBQUc7QUFDL0Isa0JBQU0sSUFBSSxNQUFNLHFEQUFxRDtBQUFBLFVBQ3ZFO0FBQ0EsK0JBQXFCLFFBQVEsS0FBSyxDQUFDO0FBQ25DLDhCQUFvQixRQUFRLEtBQUssQ0FBQztBQUFBLFFBQ3BDLFdBQVksV0FBVyxVQUFVLEtBQUssUUFBUSxJQUFJLEtBQU8sYUFBYSxVQUFVLEtBQUssVUFBVSxJQUFJLEdBQUk7QUFDckcsZ0JBQU0sSUFBSSxNQUFNLHdFQUF3RTtBQUFBLFFBQzFGO0FBRUEsWUFBSTtBQUNKLFlBQUksT0FBTyxVQUFVLEtBQUssSUFBSSxJQUFJLElBQUksR0FBRztBQUN2QyxjQUFJLE1BQU0sS0FBSyxXQUFXLEdBQUc7QUFDM0Isa0JBQU0sSUFBSSxNQUFNLGtFQUFrRTtBQUFBLFVBQ3BGO0FBQ0EsY0FBSSxJQUFJLEtBQUssU0FBUyxLQUFLLElBQUksS0FBSyxTQUFTLEdBQUc7QUFDOUMsa0JBQU0sSUFBSSxNQUFNLHVEQUF1RDtBQUFBLFVBQ3pFO0FBQ0EsY0FBSSxNQUFNLEtBQUssQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUc7QUFDakMsa0JBQU0sSUFBSSxNQUFNLDREQUE0RDtBQUFBLFVBQzlFO0FBRUEsY0FBSSxJQUFJLEtBQUssV0FBVyxHQUFHO0FBQ3pCLGdCQUFJLElBQUksS0FBSyxDQUFDLE1BQU0sTUFBTSxLQUFLLENBQUMsR0FBRztBQUNqQyxvQkFBTSxJQUFJLE1BQU0sNkRBQTZEO0FBQUEsWUFDL0U7QUFDQTtBQUNBLCtCQUFtQixJQUFJLEtBQUssQ0FBQztBQUFBLFVBQy9CLFdBQVcsSUFBSSxLQUFLLFdBQVcsR0FBRztBQUNoQyxnQkFBSSxJQUFJLEtBQUssQ0FBQyxNQUFNLFdBQVcsWUFBWSxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssSUFBSSxLQUFLLENBQUMsTUFBTSxVQUFVO0FBQ3hGLG9CQUFNLElBQUksTUFBTSw0RkFBNEY7QUFBQSxZQUM5RztBQUNBLGdCQUFJLE9BQU87QUFDVCxvQkFBTSxJQUFJLE1BQU0seURBQXlEO0FBQUEsWUFDM0U7QUFDQTtBQUNBLCtCQUFtQixJQUFJLEtBQUssQ0FBQztBQUFBLFVBQy9CLE9BQU87QUFFTCxnQkFBSSxJQUFJLEtBQUssQ0FBQyxNQUFNLFdBQVcsWUFBWSxJQUFJLEtBQUssQ0FBQyxNQUFNLFVBQVU7QUFDbkUsb0JBQU0sSUFBSSxNQUFNLHdGQUF3RjtBQUFBLFlBQzFHO0FBRUE7QUFDQSwrQkFBbUIsSUFBSSxLQUFLLENBQUM7QUFBQSxVQUMvQjtBQUFBLFFBQ0YsT0FBTztBQUVMLGNBQUksTUFBTSxLQUFLLFdBQVcsR0FBRztBQUMzQixrQkFBTSxJQUFJLE1BQU0sa0VBQWtFO0FBQUEsVUFDcEY7QUFDQSxjQUFJLE1BQU0sS0FBSyxDQUFDLE1BQU0sV0FBVyxZQUFZLE1BQU0sS0FBSyxDQUFDLE1BQU0sR0FBRztBQUNoRSxrQkFBTSxJQUFJLE1BQU0sOEZBQThGO0FBQUEsVUFDaEg7QUFFQTtBQUFBLFFBQ0Y7QUFFQSxZQUFJLFFBQVEsVUFBVSxLQUFLLEtBQUssSUFBSSxJQUFJLEdBQUc7QUFDekMsY0FBSSxLQUFLLEtBQUssV0FBVyxHQUFHO0FBQzFCLGtCQUFNLElBQUksTUFBTSw4Q0FBOEM7QUFBQSxVQUNoRTtBQUVBLGNBQUksS0FBSztBQUNQLGdCQUFJLElBQUksS0FBSyxXQUFXLEtBQUssSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHO0FBQzlDLG9CQUFNLElBQUksTUFBTSxvQ0FBb0M7QUFBQSxZQUN0RDtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBRUEsY0FBTSxzQkFBc0IscUJBQXFCO0FBRWpELFlBQUk7QUFDSixZQUFJLGtCQUFrQixVQUFVLEtBQUssZUFBZSxJQUFJLElBQUksR0FBRztBQUM3RDtBQUNBLGdCQUFNLFdBQVcsZUFBZTtBQUNoQyxjQUFJLFNBQVMsV0FBVyxHQUFHO0FBQ3pCLGdCQUFJLFNBQVMsQ0FBQyxNQUFNLFdBQVc7QUFDN0I7QUFBQSxZQUNGLFdBQVcsU0FBUyxDQUFDLE1BQU0sSUFBSSxZQUFZLEdBQUc7QUFDNUM7QUFBQSxZQUNGO0FBQUEsVUFDRixXQUFXLFNBQVMsV0FBVyxLQUFLLFNBQVMsQ0FBQyxNQUFNLGFBQWEsU0FBUyxDQUFDLE1BQU0scUJBQXFCO0FBQ3BHO0FBQUEsVUFDRjtBQUNBLGNBQUksa0NBQTRDO0FBQzlDLGtCQUFNLElBQUksTUFBTSw2RkFBNkY7QUFBQSxVQUMvRztBQUNBLGdCQUFNLElBQUksTUFBTSxvQkFBb0I7QUFBQSxRQUN0QztBQUVBLFlBQUksZUFBZTtBQUNuQixZQUFJLGNBQWM7QUFDbEIsWUFBSSxTQUFTLFVBQVUsS0FBSyxNQUFNLElBQUksSUFBSSxHQUFHO0FBQzNDLGNBQUksTUFBTSxLQUFLLFdBQVcsS0FBSyxNQUFNLEtBQUssV0FBVyxHQUFHO0FBQ3RELGtCQUFNLElBQUksTUFBTSxxREFBcUQ7QUFBQSxVQUN2RTtBQUVBLGNBQUksTUFBTSxLQUFLLENBQUMsTUFBTSxNQUFNLEtBQUssQ0FBQyxHQUFHO0FBQ25DLGtCQUFNLElBQUksTUFBTSw4REFBOEQ7QUFBQSxVQUNoRjtBQUVBLGNBQUksTUFBTSxLQUFLLFdBQVcsR0FBRztBQUMzQixnQkFBSSxxQkFBcUIsTUFBTSxLQUFLLENBQUMsR0FBRztBQUN0QyxvQkFBTSxJQUFJLE1BQU0sd0VBQXdFO0FBQUEsWUFDMUY7QUFDQSwwQkFBYyxNQUFNLEtBQUssQ0FBQztBQUFBLFVBQzVCLE9BQU87QUFFTCxnQkFBSSxxQkFBcUIsTUFBTSxLQUFLLENBQUMsR0FBRztBQUN0QyxvQkFBTSxJQUFJLE1BQU0sd0VBQXdFO0FBQUEsWUFDMUY7QUFDQSwwQkFBYyxNQUFNLEtBQUssQ0FBQyxJQUFJLE1BQU0sS0FBSyxDQUFDO0FBQzFDLDJCQUFlO0FBQUEsVUFDakI7QUFBQSxRQUNGO0FBRUEsY0FBTSxzQkFBc0I7QUFFNUIsWUFBSSxrQkFBa0IsVUFBVSxLQUFLLGVBQWUsSUFBSSxJQUFJLEdBQUc7QUFDN0QsZ0JBQU0sSUFBSSxNQUFNLG1DQUFtQztBQUFBLFFBQ3JEO0FBRUEsWUFBSSxpQkFBaUIsVUFBVSxLQUFLLGNBQWMsSUFBSSxJQUFJLEdBQUc7QUFDM0QsY0FBSSxjQUFjLEtBQUssV0FBVyxHQUFHO0FBQ25DLGtCQUFNLElBQUksTUFBTSx5REFBeUQ7QUFBQSxVQUMzRTtBQUdBLGNBQ0UsY0FBYyxLQUFLLENBQUMsTUFBTSxhQUMxQixjQUFjLEtBQUssQ0FBQyxNQUFNLFdBQVcsWUFDckMsY0FBYyxLQUFLLENBQUMsTUFBTSxrQkFDMUIsY0FBYyxLQUFLLENBQUMsTUFBTSxxQkFDMUI7QUFDQSxrQkFBTSxJQUFJLE1BQU0sK0ZBQStGO0FBQUEsVUFDakg7QUFBQSxRQUNGO0FBRUEsZUFBTztBQUFBLFVBQ0w7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0EsaUJBQWlCO0FBQUEsVUFDakI7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0EsV0FBVyxLQUFLLE1BQU0sY0FBYyxXQUFXLFFBQVE7QUFBQSxVQUN2RCxVQUFVLFdBQVc7QUFBQSxVQUNyQixrQkFBa0I7QUFBQSxVQUNsQix3QkFBd0I7QUFBQSxVQUN4QixpQkFBaUIsV0FBVztBQUFBLFVBQzVCO0FBQUEsVUFDQSxPQUFPLFdBQVc7QUFBQSxVQUNsQjtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLG9DQUFvQyxDQUFDLGVBQ2hELDRCQUE0QixFQUFFLEdBQUcsV0FBVyxDQUFDO0FBRS9DLE1BQU1DLDRCQUFnRCw0QkFBNEIsRUFBRSxNQUFNLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxFQUFFLENBQUM7QUFFeEcsTUFBTSxtQkFBbUIsQ0FDdkIsU0FDQSxLQUNBLE1BQ0EsV0FDQSxnQkFDQSxZQUNBLGVBQ0c7QUFDSCxjQUFNLGNBQWMsQ0FBQyxXQUFXLGdCQUFnQixVQUFVO0FBQzFELGNBQU0sYUFBYSxVQUFVLEtBQUssV0FBVztBQUM3QyxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFFBQzVDO0FBRUEsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFDdEQsZ0JBQU0sU0FBUyxlQUFlLGlCQUFpQixJQUFJLFVBQVUsV0FBVztBQUN4RSxnQkFBTSxXQUFXLGNBQWMsT0FBTyxJQUFJLFVBQVUsV0FBVztBQUMvRCxnQkFBTSxZQUFZLGNBQWMsUUFBUSxLQUFLLFVBQVUsV0FBVztBQUVsRSxnQkFBTSxXQUE4QjtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxlQUFlLE1BQU0sTUFBTTtBQUFBLFlBQ25DLEVBQUUsTUFBTSxlQUFlLE1BQU0sTUFBTTtBQUFBLFlBQ25DLEVBQUUsTUFBTSxlQUFlLE1BQU0sTUFBTTtBQUFBLFVBQ3JDO0FBQ0EsaUJBQU87QUFBQSxJQUNQLGFBQWEsaUJBQWlCLFFBQVEsRUFBRSxpQkFBaUIsVUFBVSxXQUFXLE1BQU0sQ0FBQztBQUFBLElBQ3JGLGFBQWEsVUFBVSxDQUFDO0FBQUEsTUFDdEIsYUFBYSxzQ0FBc0Msc0JBQXNCLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBSzlFO0FBRUEsZUFBTyxRQUFRO0FBQUEsVUFDYjtBQUFBLFlBQ0UsTUFBTTtBQUFBLFlBQ04sYUFBYSxFQUFFLG1CQUFtQixDQUFDLFFBQVEsTUFBTSxFQUFFO0FBQUEsWUFDbkQsWUFBWSxPQUFPO0FBQUEsY0FDakIsU0FBUyxDQUFDLEVBQUUsTUFBTSxhQUFhLFVBQVUsSUFBSSxVQUFVLDZCQUFpQyxDQUFDO0FBQUEsY0FDekYsZUFBZSxFQUFFLEdBQUcsS0FBSztBQUFBLGdCQUFLLGFBQWE7QUFBQTtBQUFBLGNBQXVCLEVBQUU7QUFBQSxjQUNwRTtBQUFBLFlBQ0Y7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUFBLFVBQ0EsRUFBRSxRQUFRLENBQUMsS0FBSyxJQUFJLEdBQUcsU0FBUyxDQUFDLEVBQUUsRUFBRTtBQUFBLFFBQ3ZDLEVBQUUsQ0FBQztBQUFBLE1BQ0w7QUFFTyxNQUFNLGlDQUFpQyxDQUM1QyxTQUNBLFdBQ0EsVUFDQSxnQkFDQSxVQUNBLE9BQ0EsTUFDQSxlQUNHO0FBR0gsWUFBSSxnQkFBZ0I7QUFDcEIsWUFBSSxFQUFFLFFBQVEsVUFBVSxLQUFLLEtBQUssSUFBSSxJQUFJLElBQUk7QUFDNUMsY0FBSSxNQUFNLEtBQUssV0FBVyxHQUFHO0FBQzNCLDRCQUFnQixNQUFNLFFBQVEsQ0FBQyxXQUFXLGdCQUFnQixVQUFVLFFBQVEsQ0FBQztBQUFBLFVBQy9FO0FBQ0EsY0FBSSxhQUFhLEtBQUssbUJBQW1CLEdBQUc7QUFDMUMsbUJBQU87QUFBQSxVQUNUO0FBQ0EsaUJBQU8sUUFBUSxRQUFRLDJCQUEyQixlQUFlQSwwQkFBeUIsSUFBSSxHQUFHO0FBQUEsWUFDL0YsUUFBUSxDQUFDLGFBQWE7QUFBQSxZQUN0QixTQUFTLENBQUMsRUFBRTtBQUFBLFVBQ2QsQ0FBQyxFQUFFLENBQUM7QUFBQSxRQUNOLE9BQU87QUFDTCxjQUFJLG1CQUFtQixHQUFHO0FBQ3hCLGtCQUFNLElBQUksTUFBTSxtRkFBbUY7QUFBQSxVQUNyRyxPQUFPO0FBQ0wsNEJBQWdCO0FBQUEsY0FDZDtBQUFBLGNBQ0E7QUFBQSxjQUNBO0FBQUEsY0FDQTtBQUFBLGNBQ0E7QUFBQSxjQUNBLFdBQVc7QUFBQSxjQUNYO0FBQUEsWUFDRjtBQUNBLDRCQUFnQixjQUFjLFFBQVEsQ0FBQyxXQUFXLGdCQUFnQixVQUFVLFFBQVEsQ0FBQztBQUNyRixnQkFBSSxhQUFhLEtBQUssbUJBQW1CLEdBQUc7QUFDMUMscUJBQU87QUFBQSxZQUNUO0FBQ0EsbUJBQU8sUUFBUSxRQUFRLDJCQUEyQixlQUFlQSwwQkFBeUIsSUFBSSxHQUFHO0FBQUEsY0FDL0YsUUFBUSxDQUFDLGFBQWE7QUFBQSxjQUN0QixTQUFTLENBQUMsRUFBRTtBQUFBLFlBQ2QsQ0FBQyxFQUFFLENBQUM7QUFBQSxVQUNOO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLHFCQUFxQixDQUFDLFNBQXlCLGVBQXFDO0FBQy9GLGNBQU0sU0FBU0QsaUJBQWUsUUFBUSxRQUFRLFVBQVU7QUFDeEQsY0FBTSxRQUFRLFFBQVEsT0FBTyxDQUFDO0FBQzlCLGNBQU0sTUFBTSxTQUFTLFFBQVEsUUFBUSxDQUFDO0FBQ3RDLGNBQU0sUUFBUSxTQUFTLFFBQVEsUUFBUSxDQUFDO0FBQ3hDLGNBQU0sT0FBTyxTQUFTLFFBQVEsUUFBUSxDQUFDO0FBQ3ZDLGNBQU0saUJBQWlCLFNBQVMsUUFBUSxRQUFRLENBQUM7QUFDakQsY0FBTSxnQkFBZ0IsU0FBUyxRQUFRLFFBQVEsQ0FBQztBQUNoRCxjQUFNLFVBQVUsU0FBUyxRQUFRLFFBQVEsQ0FBQztBQUMxQyxjQUFNLFlBQVksU0FBUyxRQUFRLFFBQVEsQ0FBQztBQUM1QyxZQUFJLE1BQU0sS0FBSyxXQUFXLEdBQUc7QUFDM0IsZ0JBQU0sSUFBSSxNQUFNLCtCQUErQjtBQUFBLFFBQ2pEO0FBRUEsWUFBSSxLQUFLLEtBQUssV0FBVyxHQUFHO0FBQzFCLGdCQUFNLElBQUksTUFBTSw4QkFBOEI7QUFBQSxRQUNoRDtBQUdBLGNBQU0sU0FBUyxPQUFPLFNBQVMsSUFBSSxLQUFLLFdBQVcsS0FBSyxNQUFNLEtBQUssV0FBVztBQUU5RSxjQUFNLElBQUk7QUFBQSxVQUNSO0FBQUEsVUFDQSxPQUFPO0FBQUEsVUFDUCxPQUFPO0FBQUEsVUFDUCxPQUFPO0FBQUEsVUFDUCxPQUFPO0FBQUEsVUFDUDtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsUUFDRjtBQUVBLFlBQUksUUFBUTtBQUNWLGlCQUFPLGVBQWUsU0FBUyxHQUFHLEtBQUssT0FBTyxnQkFBZ0IsUUFBVyxTQUFTLFdBQVcsZUFBZSxNQUFNO0FBQUEsUUFDcEg7QUFDQSxZQUFJLENBQUMsT0FBTyxDQUFDLE9BQU87QUFDbEIsZ0JBQU0sSUFBSSxNQUFNLGdDQUFnQztBQUFBLFFBQ2xEO0FBQ0EsY0FBTSxJQUFJO0FBQUEsVUFDUjtBQUFBLFVBQ0EsT0FBTztBQUFBLFVBQ1AsT0FBTztBQUFBLFVBQ1AsT0FBTztBQUFBLFVBQ1AsT0FBTztBQUFBLFVBQ1A7QUFBQSxVQUNBO0FBQUEsVUFDQSxPQUFPO0FBQUEsUUFDVDtBQUVBLGNBQU0sSUFBSTtBQUFBLFVBQ1I7QUFBQSxVQUNBLE9BQU87QUFBQSxVQUNQLE9BQU87QUFBQSxVQUNQLE9BQU87QUFBQSxVQUNQLE9BQU87QUFBQSxVQUNQO0FBQUEsVUFDQTtBQUFBLFVBQ0EsSUFBSSxPQUFPO0FBQUEsUUFDYjtBQUVBLHVCQUFlLFNBQVMsR0FBRyxHQUFHLEdBQUcsZ0JBQWdCLFFBQVcsU0FBUyxXQUFXLGVBQWUsTUFBTTtBQUFBLE1BQ3ZHO0FBQUE7QUFBQTs7O0FDamJBLE1Bd0JNRSxrQkFNQSxpQ0FhQSwwQkFTQSxxQkFxQk8sd0JBeURBLE9BT0E7QUF6SWI7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUNBO0FBR0E7QUFlQSxNQUFNQSxtQkFBaUIsQ0FBQyxXQUF3QztBQUM5RCxZQUFJLENBQUMsVUFBVSxPQUFPLFNBQVMsR0FBRztBQUNoQyxnQkFBTSxJQUFJLE1BQU0sZ0JBQWdCO0FBQUEsUUFDbEM7QUFBQSxNQUNGO0FBRUEsTUFBTSxrQ0FBa0MsQ0FDdEMsUUFDQSxlQUNvQjtBQUNwQixjQUFNLGFBQXVCLENBQUM7QUFDOUIsWUFBSSxhQUFxQixXQUFXO0FBQ3BDLFlBQUksT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLElBQUksR0FBRztBQUN6QixpQkFBTyxDQUFDLEVBQUUsaUJBQWlCLEVBQUUsUUFBUSxDQUFDLE1BQU0sV0FBVyxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFDdEUsdUJBQWEsV0FBVztBQUFBLFFBQzFCO0FBQ0EsZUFBTyw0QkFBNEIsRUFBRSxZQUFZLE1BQU0sV0FBVyxNQUFNLFdBQVcsQ0FBQztBQUFBLE1BQ3RGO0FBRUEsTUFBTSwyQkFBMkIsQ0FBQyxvQkFBb0M7QUFBQTtBQUFBLGdDQUV0QyxlQUFlO0FBQUEsa0JBQzdCLGFBQWEsK0JBQStCLEtBQUssZUFBZSxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUEsYUFJdEUsZUFBZTtBQUFBO0FBRTVCLE1BQU0sc0JBQXNCLENBQUMsWUFBc0M7QUFDakUsY0FBTSxrQkFBa0IsUUFBUTtBQUNoQyxjQUFNLFlBQXNCLENBQUM7QUFDN0IsaUJBQVMsSUFBSSxHQUFHLElBQUksaUJBQWlCLEVBQUUsR0FBRztBQUN4QyxnQkFBTSxnQkFBZ0IsUUFBUSxDQUFDLEVBQUUsYUFBYSxXQUFXLG1CQUFtQjtBQUM1RSxjQUFJLG9CQUFvQixHQUFHO0FBQ3pCLHNCQUFVLEtBQUssYUFBYTtBQUFBLFVBQzlCLFdBQVcsTUFBTSxHQUFHO0FBQ2xCLHNCQUFVLEtBQUssd0JBQXdCLENBQUMsUUFBUSxhQUFhLElBQUk7QUFBQSxVQUNuRSxXQUFXLE1BQU0sa0JBQWtCLEdBQUc7QUFDcEMsc0JBQVUsS0FBSyxVQUFVLGFBQWEsSUFBSTtBQUFBLFVBQzVDLE9BQU87QUFDTCxzQkFBVSxLQUFLLDZCQUE2QixDQUFDLE9BQU8sYUFBYSxJQUFJO0FBQUEsVUFDdkU7QUFBQSxRQUNGO0FBQ0EsZUFBTztBQUFBLHdEQUMrQyxRQUFRLENBQUMsRUFBRSxLQUFLLE9BQU87QUFBQSxVQUNyRSxVQUFVLEtBQUssSUFBSSxDQUFDO0FBQUE7QUFBQSxNQUU5QjtBQUVPLE1BQU0seUJBQXlCLENBQUMsUUFBK0IsZUFBNkM7QUFDakgsY0FBTSxhQUFhLE9BQU8sQ0FBQyxFQUFFO0FBQzdCLGNBQU0sWUFBWSxVQUFVLEtBQUssVUFBVTtBQUMzQyxjQUFNLFdBQVcsT0FBTyxDQUFDLEVBQUU7QUFDM0IsY0FBTSxPQUFPLFVBQVUsY0FBYyxXQUFXLE1BQU0sV0FBVyxNQUFNO0FBQ3ZFLGNBQU0sVUFBVSxJQUFJLE1BQXFCLFdBQVcsVUFBVTtBQUM5RCxjQUFNLFFBQVEsY0FBYyxTQUFTLFVBQVUsV0FBVyxNQUFNO0FBQ2hFLGNBQU0sa0JBQWtCLElBQUksTUFBYyxXQUFXLFVBQVU7QUFDL0QsY0FBTSxvQkFBa0MsQ0FBQztBQUN6QyxjQUFNLGVBQTJCLENBQUM7QUFDbEMsWUFBSSxjQUFjO0FBQ2xCLGNBQU0sa0JBQW9DLENBQUMsRUFBRSx1QkFBdUIsTUFBTSxVQUFVLENBQUM7QUFDckYsaUJBQVMsSUFBSSxHQUFHLElBQUksV0FBVyxZQUFZLEtBQUs7QUFDOUMseUJBQWUsV0FBVyxXQUFXLENBQUM7QUFDdEMsMEJBQWdCLENBQUMsSUFBSTtBQUNyQixnQkFBTSxjQUFjLFdBQVcsTUFBTTtBQUNyQyxzQkFBWSxJQUFJLElBQUksV0FBVyxXQUFXLENBQUM7QUFDM0MsdUJBQWEsS0FBSyxXQUFXO0FBQzdCLGtCQUFRLENBQUMsSUFBSSxlQUFlLFNBQVMsQ0FBQyxJQUFJLFVBQVUsWUFBWSxNQUFNO0FBQ3RFLDRCQUFrQixLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUMsR0FBRyxVQUFVLE9BQU8sQ0FBQyxFQUFFLFNBQVMsQ0FBQztBQUFBLFFBQ2hGO0FBQ0Esd0JBQWdCO0FBQUEsVUFDZCxFQUFFLHVCQUF1QixNQUFNLGdCQUFnQjtBQUFBLFVBQy9DLEdBQUcsMkJBQTJCLFlBQVksR0FBRyxZQUFZO0FBQUEsUUFDM0Q7QUFDQSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUFBLElBQ3RELGFBQ0MsZ0JBQWdCLGNBQWMsS0FBSyxFQUNuQyxnQkFBZ0Isc0JBQXNCLE9BQU8sZ0JBQWdCLE1BQU0sRUFDbkUsaUJBQWlCLE9BQU8sR0FBRyxPQUFPLENBQUM7QUFBQSxJQUNwQyx5QkFBeUIsZ0JBQWdCLE1BQU0sQ0FBQztBQUFBLElBQ2hELG9CQUFvQixPQUFPLENBQUM7QUFBQTtBQUFBLElBRTVCLGFBQWEsVUFBVSxDQUFDO0FBQUEsTUFDdEIsYUFBYSxzQ0FBc0MscUJBQXFCLENBQUM7QUFBQTtBQUFBLG9CQUUzRCxNQUFNLGdCQUFnQixZQUFZLENBQUM7QUFBQSxrQkFDckMsTUFBTSxXQUFXLFdBQVcsSUFBSSxDQUFDO0FBQUE7QUFBQTtBQUFBLGlCQUdsQyxhQUFhLCtCQUErQixzQkFBc0IsZ0JBQWdCLE1BQU0sQ0FBQztBQUFBLFFBQ2xHLE1BQU0sV0FBVyxXQUFXLE1BQU0sT0FBTyxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBSWhELGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWEsRUFBRSxNQUFNLFdBQVcsVUFBVSxtQkFBbUIsQ0FBQyxNQUFNLEVBQUU7QUFBQSxVQUN0RTtBQUFBLFVBQ0EsWUFBWSxPQUFPO0FBQUEsWUFDakIsU0FBUztBQUFBLFlBQ1QsZUFBZSxFQUFFLEdBQUcsS0FBSztBQUFBLGNBQUssWUFBWTtBQUFBO0FBQUEsWUFBdUIsRUFBRTtBQUFBLFlBQ25FO0FBQUEsVUFDRjtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxRQUFRLENBQUMsU0FBeUIsZUFBc0M7QUFDbkYsUUFBQUEsaUJBQWUsUUFBUSxNQUFNO0FBQzdCLGNBQU0sb0JBQ0osUUFBUSxPQUFPLFdBQVcsSUFBSSxhQUFhLGdDQUFnQyxRQUFRLFFBQVEsVUFBVTtBQUN2RyxnQkFBUSxRQUFRLHVCQUF1QixRQUFRLFFBQVEsaUJBQWlCLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFBQSxNQUM1RjtBQUVPLE1BQU0sdUJBQXVCLENBQUMsZUFBeUQ7QUFDNUYsY0FBTSxPQUFPLFdBQVc7QUFDeEIsY0FBTSxhQUF1QixXQUFXO0FBQ3hDLGNBQU0sYUFBYyxXQUFXLGFBQXdCLElBQUksV0FBVyxTQUFVLFdBQVc7QUFDM0YsWUFBSSxlQUFlLFdBQVcsUUFBUTtBQUNwQyxnQkFBTSxJQUFJLE1BQU0sK0NBQStDO0FBQUEsUUFDakU7QUFDQSxlQUFPLDRCQUE0QixFQUFFLE1BQU0sWUFBWSxXQUFXLENBQUM7QUFBQSxNQUNyRTtBQUFBO0FBQUE7OztBQ2pKQSxNQWtCTUMsa0JBMkRPLGtDQXVHQTtBQXBMYjtBQUFBO0FBQUE7QUFHQTtBQUVBO0FBQ0E7QUFHQTtBQVNBLE1BQU1BLG1CQUFpQixDQUFDLFFBQStCLGVBQWdEO0FBQ3JHLGNBQU0sQ0FBQyxPQUFPLGFBQWEsVUFBVSxRQUFRLElBQUk7QUFDakQsY0FBTSxFQUFFLFVBQVUsbUJBQW1CLElBQUk7QUFFekMsWUFBSSxNQUFNLEtBQUssV0FBVyxLQUFLLE1BQU0sS0FBSyxXQUFXLEdBQUc7QUFDdEQsZ0JBQU0sSUFBSSxNQUFNLHdEQUF3RCxNQUFNLEtBQUssTUFBTSxFQUFFO0FBQUEsUUFDN0Y7QUFDQSxZQUNFLENBQUMsVUFBVSxTQUFTLFlBQVksTUFBTSxDQUFDLENBQUMsS0FDeEMsQ0FBQyxVQUFVLFNBQVMsWUFBWSxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQ3pDLFlBQVksS0FBSyxXQUFXLEdBQzVCO0FBQ0EsZ0JBQU0sSUFBSSxNQUFNLHVFQUF1RSxZQUFZLEtBQUssTUFBTSxFQUFFO0FBQUEsUUFDbEg7QUFDQSxZQUFJLFNBQVMsS0FBSyxXQUFXLEdBQUc7QUFDOUIsZ0JBQU0sSUFBSSxNQUFNLDJEQUEyRCxTQUFTLEtBQUssTUFBTSxFQUFFO0FBQUEsUUFDbkc7QUFDQSxZQUFJLFNBQVMsS0FBSyxXQUFXLEdBQUc7QUFDOUIsZ0JBQU0sSUFBSSxNQUFNLDJEQUEyRCxTQUFTLEtBQUssTUFBTSxFQUFFO0FBQUEsUUFDbkc7QUFDQSxZQUFJLENBQUMsVUFBVSxTQUFTLFNBQVMsTUFBTSxTQUFTLElBQUksR0FBRztBQUNyRCxnQkFBTSxJQUFJLE1BQU0sd0VBQXdFO0FBQUEsUUFDMUY7QUFFQSxZQUFJLHFCQUFxQixLQUFLLGFBQWEsR0FBRztBQUM1QyxnQkFBTSxJQUFJLE1BQU0saUVBQWlFO0FBQUEsUUFDbkY7QUFFQSxjQUFNLFlBQVksTUFBTSxLQUFLLENBQUM7QUFDOUIsY0FBTSxpQkFBaUIsTUFBTSxLQUFLLE1BQU0sS0FBSyxTQUFTLENBQUM7QUFDdkQsY0FBTSxvQkFBb0IsU0FBUyxLQUFLLENBQUM7QUFDekMsY0FBTSxhQUFhLFVBQVUsa0JBQWtCLE1BQU0sTUFBTSxDQUFDLElBQUk7QUFDaEUsY0FBTSxXQUFXLHVCQUF1QixJQUFJLFNBQVMsS0FBSyxDQUFDLElBQUksSUFBSSxhQUFhO0FBQ2hGLFlBQUkscUJBQXFCLFVBQVU7QUFDakMsZ0JBQU0sSUFBSSxNQUFNLDhEQUE4RDtBQUFBLFFBQ2hGO0FBRUEsWUFBSSxZQUFZLEtBQUssV0FBVyxHQUFHO0FBQ2pDLGNBQUksY0FBYyxZQUFZLEtBQUssQ0FBQyxHQUFHO0FBQ3JDLGtCQUFNLElBQUksTUFBTSxzRUFBc0UsWUFBWSxLQUFLLENBQUMsQ0FBQyxFQUFFO0FBQUEsVUFDN0c7QUFDQSxjQUFJLG1CQUFtQixZQUFZLEtBQUssQ0FBQyxHQUFHO0FBQzFDLGtCQUFNLElBQUksTUFBTSwyRUFBMkUsWUFBWSxLQUFLLENBQUMsQ0FBQyxFQUFFO0FBQUEsVUFDbEg7QUFBQSxRQUNGO0FBRUEsWUFBSSxXQUFXLE1BQU0sU0FBUyxLQUFLLENBQUMsS0FBSyxxQkFBcUIsTUFBTSxTQUFTLEtBQUssQ0FBQyxHQUFHO0FBQ3BGLGdCQUFNLElBQUk7QUFBQSxZQUNSLGtHQUNFLFNBQVMsS0FBSyxDQUFDLENBQ2pCO0FBQUEsVUFDRjtBQUFBLFFBQ0Y7QUFFQSxZQUFJLGlCQUFpQixtQkFBbUI7QUFDdEMsZ0JBQU0sSUFBSSxNQUFNLGdGQUFnRjtBQUFBLFFBQ2xHO0FBQUEsTUFDRjtBQUVPLE1BQU0sbUNBQW1DLENBQzlDLFFBQ0EsZUFDZ0I7QUFDaEIsY0FBTSxFQUFFLGFBQWEsVUFBVSxvQkFBb0IsTUFBTSxJQUFJO0FBQzdELGNBQU0sWUFBWSxPQUFPLENBQUMsRUFBRSxLQUFLLENBQUM7QUFDbEMsY0FBTSxjQUFjLFVBQVUsa0JBQWtCLE9BQU8sQ0FBQyxFQUFFLE1BQU0sQ0FBQztBQUNqRSxjQUFNLGlCQUFpQixPQUFPLENBQUMsRUFBRSxLQUFLLE9BQU8sQ0FBQyxFQUFFLEtBQUssU0FBUyxDQUFDO0FBQy9ELGNBQU0sYUFBYSxjQUFjO0FBQ2pDLGNBQU0seUJBQXlCLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQztBQUMvQyxjQUFNLFdBQVcsdUJBQXVCLElBQUkseUJBQXlCLElBQUksYUFBYTtBQUt0RixjQUFNLGNBQWMsSUFBSTtBQUFBLFVBQ3RCO0FBQUEsVUFDQTtBQUFBLFVBQ0EsYUFBYTtBQUFBLFVBQ2IsV0FBVztBQUFBLFFBQ2I7QUFDQSxjQUFNLGdCQUFnQixVQUFVLGVBQWUsV0FBVztBQUUxRCxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUscUJBQXNCLE1BQU0sTUFBTTtBQUFBLFVBQ3BDLEVBQUUsdUJBQXVCLE1BQU0sWUFBWTtBQUFBLFVBQzNDLEVBQUUsdUJBQXVCLE1BQU0sY0FBYztBQUFBO0FBQUE7QUFBQSxVQUk3QyxHQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssV0FBVyxJQUMxQixJQUFJLE1BQXNCLEVBQUUsdUJBQXVCLE1BQU0sQ0FBQyxhQUFhLFlBQVksVUFBVSxDQUFDLEVBQUUsQ0FBQyxJQUNqRyxDQUFDO0FBQUEsVUFDTCxHQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssV0FBVyxJQUMxQixJQUFJLE1BQXNCO0FBQUEsWUFDeEI7QUFBQSxZQUNBLE1BQU0sQ0FBQyxhQUFhLFVBQVUsaUJBQWlCLFVBQVUsQ0FBQztBQUFBLFVBQzVELENBQUMsSUFDRCxDQUFDO0FBQUEsVUFFTCxHQUFHLDJCQUEyQixPQUFPLENBQUMsRUFBRSxNQUFNLE9BQU8sQ0FBQyxFQUFFLE1BQU0sT0FBTyxDQUFDLEVBQUUsTUFBTSxPQUFPLENBQUMsRUFBRSxNQUFNLE9BQU8sQ0FBQyxFQUFFLElBQUk7QUFBQSxRQUM5RztBQUVBLGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQ3RELGdCQUFNLFFBQVEsY0FBYyxTQUFTLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxDQUFDLEVBQUUsS0FBSyxNQUFNO0FBQzlFLGdCQUFNLGNBQWMsY0FBYyxnQkFBZ0IsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU07QUFDM0YsZ0JBQU0sV0FBVyxjQUFjLGFBQWEsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU07QUFDckYsZ0JBQU0sV0FBVyxjQUFjLGFBQWEsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU07QUFDckYsZ0JBQU0sU0FBUyxlQUFlLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU07QUFFakYsdUJBQWEsaUJBQWlCO0FBQUEsWUFDNUIsRUFBRSxNQUFNLFNBQVMsTUFBTSxNQUFNO0FBQUEsWUFDN0IsRUFBRSxNQUFNLGdCQUFnQixNQUFNLE9BQU8sUUFBUSxZQUFZLE9BQU87QUFBQSxZQUNoRSxFQUFFLE1BQU0sa0JBQWtCLE1BQU0sT0FBTyxRQUFRLGNBQWMsT0FBTztBQUFBLFlBQ3BFLEVBQUUsTUFBTSx3QkFBd0IsTUFBTSxPQUFPLFFBQVEsY0FBYyxPQUFPO0FBQUEsVUFDNUUsQ0FBQztBQUVELGlCQUFPO0FBQUEsVUFDRCxhQUFhLGlCQUFpQixPQUFPLGFBQWEsVUFBVSxVQUFVLE1BQU0sQ0FBQztBQUFBO0FBQUEsVUFFN0UsYUFBYSxVQUFVLGNBQWMsQ0FBQztBQUFBLCtDQUNELFNBQVMsSUFBSTtBQUFBO0FBQUE7QUFBQSxZQUdoRCxhQUFhLHNDQUFzQyxNQUFNLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQSxrQkFJcEQsWUFBWSwyQkFBMkIsV0FBVyxlQUFlLElBQUksWUFBWSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUM7QUFBQTtBQUFBLHNCQUU3RixZQUFZLFlBQVksa0JBQWtCLENBQUM7QUFBQSxvRkFDbUIsV0FBVztBQUFBLHlEQUN0QyxXQUFXO0FBQUEsdUJBQzdDLE1BQU0sWUFBWSxHQUFHLENBQUMsTUFBTSxTQUFTLElBQUksZUFBZSxTQUFTLENBQUM7QUFBQSxrQkFDdkUsTUFBTSxZQUFZLEdBQUcsQ0FBQyxNQUFNLFNBQVMsSUFBSSxlQUFlLFNBQVMsQ0FBQztBQUFBLGNBQ3RFLE9BQU8sWUFBWSxLQUFLLElBQUksQ0FBQztBQUFBLHVCQUNwQixNQUFNLFlBQVksR0FBRyxDQUFDLE1BQU0sU0FBUyxJQUFJLGVBQWUsU0FBUyxDQUFDO0FBQUEsa0JBQ3ZFLE1BQU0sWUFBWSxHQUFHLENBQUMsTUFBTSxTQUFTLElBQUksZUFBZSxTQUFTLENBQUM7QUFBQSxjQUN0RSxPQUFPLFlBQVksS0FBSyxJQUFJLENBQUM7QUFBQTtBQUFBO0FBQUEsY0FHN0IsT0FBTyxZQUFZLEtBQUssTUFBTSxZQUFZLEdBQUcsQ0FBQyxDQUFDO0FBQUE7QUFBQTtBQUFBLFFBRzNEO0FBRUEsZUFBTztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sYUFBYTtBQUFBLFlBQ1gsTUFBTSw0QkFBNEI7QUFBQSxjQUNoQztBQUFBLFlBQ0YsQ0FBQyxFQUFFO0FBQUEsWUFDSCxtQkFBbUIsQ0FBQyxRQUFRLFFBQVEsUUFBUSxNQUFNO0FBQUEsVUFDcEQ7QUFBQSxVQUNBO0FBQUEsVUFDQSxZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLE9BQU8sQ0FBQyxFQUFFLE1BQU0sVUFBVSxPQUFPLENBQUMsRUFBRSxTQUFTLENBQUM7QUFBQSxZQUNoRSxlQUFlLEVBQUUsR0FBRyxLQUFLLEtBQUssVUFBVSxLQUFLLFdBQVcsSUFBSSxjQUFjLEVBQUU7QUFBQSxZQUM1RTtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sa0JBQWtCLENBQUMsU0FBeUIsZUFBZ0Q7QUFDdkcsUUFBQUEsaUJBQWUsUUFBUSxRQUFRLFVBQVU7QUFDekMsZ0JBQVEsUUFBUSxpQ0FBaUMsUUFBUSxRQUFRLFVBQVUsQ0FBQztBQUFBLE1BQzlFO0FBQUE7QUFBQTs7O0FDdkxBLE1BeUJhQyxrQkEwTVBDLDJCQUVBLHNCQWNBLGdDQXVFTztBQTFUYjtBQUFBO0FBQUE7QUFJQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBWU8sTUFBTUQsbUJBQWlCLENBQzVCLFFBQ0EsZUFDd0I7QUFDeEIsWUFBSSxXQUFXLFlBQVksT0FBTyxVQUFVLEdBQUc7QUFDN0MsZ0JBQU0sSUFBSSxNQUFNLHVFQUF1RTtBQUFBLFFBQ3pGO0FBQ0EsY0FBTSxRQUFRLE9BQU8sQ0FBQztBQUN0QixjQUFNLE1BQU0sT0FBTyxDQUFDO0FBQ3BCLGNBQU0sUUFBUSxPQUFPLENBQUM7QUFDdEIsY0FBTSxVQUFVLE9BQU8sQ0FBQztBQUN4QixjQUFNLFlBQVksT0FBTyxDQUFDO0FBQzFCLFlBQUksV0FBVyxhQUFhLEtBQUssT0FBTyxVQUFVLEdBQUc7QUFDbkQsZ0JBQU0sSUFBSSxNQUFNLHdFQUF3RTtBQUFBLFFBQzFGO0FBQ0EsWUFBSSxXQUFXLG9CQUFvQixJQUFJO0FBQ3JDLGdCQUFNLElBQUksTUFBTSxrQ0FBa0M7QUFBQSxRQUNwRDtBQUNBLFlBQUksV0FBVyxZQUFZLEdBQUc7QUFDNUIsZ0JBQU0sSUFBSSxNQUFNLDBCQUEwQjtBQUFBLFFBQzVDO0FBQ0EsWUFBSSxXQUFXLHNCQUFzQixHQUFHO0FBQ3RDLGdCQUFNLElBQUksTUFBTSxxQ0FBcUM7QUFBQSxRQUN2RDtBQUNBLFlBQUksV0FBVyxlQUFlO0FBQzVCLGdCQUFNLElBQUksTUFBTSxpQ0FBaUM7QUFBQSxRQUNuRDtBQThCQSxZQUFJLE1BQU0sS0FBSyxXQUFXLEtBQUssTUFBTSxLQUFLLFdBQVcsR0FBRztBQUN0RCxnQkFBTSxJQUFJLE1BQU0sbURBQW1EO0FBQUEsUUFDckU7QUFFQSxjQUFNLGVBQWU7QUFDckIsY0FBTSxZQUFZLE1BQU0sS0FBSyxDQUFDO0FBQzlCLGNBQU0saUJBQWlCLE1BQU0sS0FBSyxDQUFDO0FBQ25DLFlBQUksYUFDRixNQUFNLEtBQUssV0FBVyxJQUFLLGVBQWUsTUFBTSxLQUFLLENBQUMsSUFBSSxJQUFJLE1BQU0sS0FBSyxDQUFDLElBQUssV0FBVyxXQUFXLE1BQU0sS0FBSyxDQUFDO0FBQ25ILFlBQUksbUJBQW1CO0FBRXZCLFlBQUkscUJBQXFCO0FBQ3pCLGNBQU0sWUFBWSxDQUFDLE9BQU8sSUFBSSxLQUFLLFdBQVc7QUFDOUMsY0FBTSxXQUFXLENBQUMsWUFDZCxLQUFLLE1BQU0sYUFBYSxXQUFXLFFBQVEsSUFDM0MsS0FBSyxNQUFNLGNBQWMsV0FBVyxXQUFXLElBQUksV0FBVyxXQUFXO0FBQzdFLFlBQUksV0FBVztBQUNiLHVCQUFhLFdBQVcsV0FBVztBQUFBLFFBQ3JDO0FBQ0EsY0FBTSxhQUFhLFdBQVcsUUFBUSxLQUFLLFdBQVc7QUFDdEQsY0FBTSxlQUFlLGFBQWEsVUFBVSxLQUFLLFdBQVc7QUFFNUQsY0FBTSxlQUNKLGNBQ0EsUUFBUSxLQUFLLFdBQVcsS0FDeEIsUUFBUSxLQUFLLENBQUMsTUFBTSxhQUNwQixRQUFRLEtBQUssQ0FBQyxNQUFNLFdBQVcsY0FDL0IsUUFBUSxLQUFLLENBQUMsTUFBTSxXQUFXLGNBQy9CLFFBQVEsS0FBSyxDQUFDLE1BQU07QUFFdEIsWUFBSSxjQUFjO0FBQ2hCLGdCQUFNLElBQUksTUFBTSx5Q0FBeUM7QUFBQSxRQUMzRDtBQUNBLFlBQUksY0FBYyxjQUFjO0FBQzlCLGNBQUksUUFBUSxLQUFLLFdBQVcsR0FBRztBQUM3QixrQkFBTSxJQUFJLE1BQU0sbURBQW1EO0FBQUEsVUFDckU7QUFDQSxjQUFJLFVBQVUsS0FBSyxXQUFXLEdBQUc7QUFDL0Isa0JBQU0sSUFBSSxNQUFNLHFEQUFxRDtBQUFBLFVBQ3ZFO0FBQ0EsK0JBQXFCLFFBQVEsS0FBSyxDQUFDO0FBQUEsUUFDckMsV0FBVyxjQUFjLGNBQWM7QUFDckMsZ0JBQU0sSUFBSSxNQUFNLHdFQUF3RTtBQUFBLFFBQzFGO0FBRUEsWUFBSTtBQUNKLFlBQUksT0FBTyxJQUFJLEtBQUssU0FBUyxHQUFHO0FBQzlCLGNBQUksTUFBTSxLQUFLLFdBQVcsR0FBRztBQUMzQixrQkFBTSxJQUFJLE1BQU0sa0VBQWtFO0FBQUEsVUFDcEY7QUFDQSxjQUFJLElBQUksS0FBSyxTQUFTLEtBQUssSUFBSSxLQUFLLFNBQVMsR0FBRztBQUM5QyxrQkFBTSxJQUFJLE1BQU0sdURBQXVEO0FBQUEsVUFDekU7QUFDQSxjQUFJLE1BQU0sS0FBSyxDQUFDLE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRztBQUNqQyxrQkFBTSxJQUFJLE1BQU0sNERBQTREO0FBQUEsVUFDOUU7QUFFQSxjQUFJLElBQUksS0FBSyxXQUFXLEdBQUc7QUFDekIsZ0JBQUksTUFBTSxLQUFLLENBQUMsSUFBSSxJQUFJLEtBQUssQ0FBQyxNQUFNLEdBQUc7QUFDckMsb0JBQU0sSUFBSSxNQUFNLHNEQUFzRDtBQUFBLFlBQ3hFO0FBQ0EsK0JBQW1CLElBQUksS0FBSyxDQUFDO0FBQUEsVUFDL0IsV0FBVyxJQUFJLEtBQUssV0FBVyxHQUFHO0FBQ2hDLGdCQUFJLElBQUksS0FBSyxDQUFDLE1BQU0sV0FBVyxZQUFZLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxJQUFJLEtBQUssQ0FBQyxNQUFNLFVBQVU7QUFDeEYsb0JBQU0sSUFBSSxNQUFNLDRGQUE0RjtBQUFBLFlBQzlHO0FBQ0EsZ0JBQUksT0FBTztBQUNULG9CQUFNLElBQUksTUFBTSx5REFBeUQ7QUFBQSxZQUMzRTtBQUNBLCtCQUFtQixJQUFJLEtBQUssQ0FBQztBQUFBLFVBQy9CLE9BQU87QUFFTCxnQkFBSSxJQUFJLEtBQUssQ0FBQyxNQUFNLFdBQVcsWUFBWSxJQUFJLEtBQUssQ0FBQyxNQUFNLFVBQVU7QUFDbkUsb0JBQU0sSUFBSSxNQUFNLHdGQUF3RjtBQUFBLFlBQzFHO0FBQ0EsK0JBQW1CLElBQUksS0FBSyxDQUFDO0FBQUEsVUFDL0I7QUFBQSxRQUNGLE9BQU87QUFFTCxjQUFJLE1BQU0sS0FBSyxXQUFXLEtBQUssTUFBTSxLQUFLLFdBQVcsR0FBRztBQUN0RCxrQkFBTSxJQUFJLE1BQU0sdUVBQXVFO0FBQUEsVUFDekY7QUFDQSxjQUFJLE1BQU0sS0FBSyxXQUFXLE1BQU0sTUFBTSxLQUFLLENBQUMsTUFBTSxXQUFXLFlBQVksTUFBTSxLQUFLLENBQUMsTUFBTSxJQUFJO0FBQzdGLGtCQUFNLElBQUksTUFBTSw4RkFBOEY7QUFBQSxVQUNoSDtBQUVBO0FBQUEsUUFDRjtBQUVBLGNBQU07QUFDTixZQUFJLGVBQWU7QUFDbkIsWUFBSSxjQUFjLFdBQVcsYUFBYSxXQUFXLFdBQVcsYUFBYTtBQUM3RSxZQUFJLFNBQVMsTUFBTSxLQUFLLFNBQVMsR0FBRztBQUNsQyxjQUFJLE1BQU0sS0FBSyxXQUFXLEtBQUssTUFBTSxLQUFLLFdBQVcsR0FBRztBQUN0RCxrQkFBTSxJQUFJLE1BQU0scURBQXFEO0FBQUEsVUFDdkU7QUFFQSxjQUFJLE1BQU0sS0FBSyxDQUFDLE1BQU0sTUFBTSxLQUFLLENBQUMsR0FBRztBQUNuQyxrQkFBTSxJQUFJLE1BQU0sOERBQThEO0FBQUEsVUFDaEY7QUFFQSxjQUFJLE1BQU0sS0FBSyxXQUFXLEdBQUc7QUFDM0IsZ0JBQUkscUJBQXFCLE1BQU0sS0FBSyxDQUFDLEdBQUc7QUFDdEMsb0JBQU0sSUFBSSxNQUFNLHdFQUF3RTtBQUFBLFlBQzFGO0FBQ0EsMEJBQWMsTUFBTSxLQUFLLENBQUM7QUFBQSxVQUM1QixPQUFPO0FBQ0wsZ0JBQUkscUJBQXFCLE1BQU0sS0FBSyxDQUFDLEdBQUc7QUFDdEMsb0JBQU0sSUFBSSxNQUFNLGtGQUFrRjtBQUFBLFlBQ3BHO0FBQ0EsMEJBQWMsTUFBTSxLQUFLLENBQUMsSUFBSSxNQUFNLEtBQUssQ0FBQztBQUMxQywyQkFBZTtBQUFBLFVBQ2pCO0FBQUEsUUFDRjtBQUNBLGNBQU0sV0FBVyxPQUFPLFNBQVMsSUFBSSxPQUFPLENBQUMsSUFBSTtBQUNqRCxZQUFJLFlBQVksU0FBUyxLQUFLLFdBQVcsS0FBSyxTQUFTLEtBQUssQ0FBQyxNQUFNLFdBQVc7QUFDNUUsZ0JBQU0sSUFBSSxNQUFNLGtGQUFrRjtBQUFBLFFBQ3BHO0FBQ0EsY0FBTSxzQkFBc0I7QUFDNUIsY0FBTSxvQkFBb0I7QUFDMUIsY0FBTSxzQkFBc0I7QUFFNUIsZUFBTztBQUFBLFVBQ0w7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0EsaUJBQWlCO0FBQUEsVUFDakI7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0EsV0FBVyxLQUFLLE1BQU0sY0FBYyxXQUFXLFVBQVU7QUFBQSxVQUN6RCxVQUFVLFdBQVc7QUFBQSxVQUNyQixZQUFZLFdBQVc7QUFBQSxVQUN2QixPQUFPLFdBQVcsV0FBVyxXQUFXO0FBQUEsVUFDeEMsd0JBQXdCO0FBQUEsVUFDeEI7QUFBQSxVQUNBLE9BQU8sV0FBVztBQUFBLFVBQ2xCO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVBLE1BQU1DLDRCQUFnRCw0QkFBNEIsRUFBRSxNQUFNLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxFQUFFLENBQUM7QUFFeEcsTUFBTSx1QkFBdUIsQ0FBQyxTQUF5QixPQUFtQixXQUFnQztBQUN4RyxZQUFJLGdCQUFnQjtBQUNwQixjQUFNLFdBQVcsT0FBTztBQUN4QixZQUFJLE1BQU0sS0FBSyxXQUFXLEtBQUssT0FBTyxxQkFBcUIsR0FBRztBQUM1RCwwQkFBZ0IsTUFBTSxRQUFRLENBQUMsT0FBTyxXQUFXLE9BQU8sa0JBQWtCLFVBQVUsT0FBTyxRQUFRLENBQUM7QUFDcEcsMEJBQWdCLFFBQVEsUUFBUSwyQkFBMkIsZUFBZUEsMEJBQXlCLElBQUksR0FBRztBQUFBLFlBQ3hHLFFBQVEsQ0FBQyxhQUFhO0FBQUEsWUFDdEIsU0FBUyxDQUFDLEVBQUU7QUFBQSxVQUNkLENBQUMsRUFBRSxDQUFDO0FBQUEsUUFDTjtBQUVBLGVBQU87QUFBQSxNQUNUO0FBRUEsTUFBTSxpQ0FBaUMsQ0FDckMsV0FDQSxnQkFDQSxTQUNBLGdCQUNHO0FBQ0gsY0FBTTtBQUNOLGNBQU0sb0JBQXdELENBQUMsUUFBUSxNQUFNO0FBQzdFLGNBQU0sY0FBYyxDQUFDLFlBQVksY0FBYztBQUMvQyxjQUFNLGFBQWEsWUFBWTtBQUMvQixjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sZUFBZTtBQUFBLFVBQzlDLEVBQUUsdUJBQXVCLE1BQU0sVUFBVTtBQUFBLFFBQzNDO0FBQ0EsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFDdEQsZ0JBQU0scUJBQXFCLGNBQWMsWUFBWSxRQUFRLFVBQVUsUUFBUSxJQUFJO0FBQ25GLGdCQUFNLHlCQUF5QixjQUFjLGtCQUFrQixZQUFZLFVBQVUsWUFBWSxJQUFJO0FBQ3JHLGdCQUFNLG9CQUFvQixlQUFlLFdBQVcsZ0JBQWdCLFdBQVc7QUFFL0UsZ0JBQU0sV0FBOEI7QUFBQSxZQUNsQyxFQUFFLE1BQU0sZUFBZSxNQUFNLE1BQU07QUFBQSxZQUNuQyxFQUFFLE1BQU0sbUJBQW1CLE1BQU0sTUFBTTtBQUFBLFlBQ3ZDLEVBQUUsTUFBTSxjQUFjLE1BQU0sTUFBTTtBQUFBLFVBQ3BDO0FBRUEsaUJBQU87QUFBQSxJQUNQLGFBQWEsaUJBQWlCLFFBQVEsRUFBRSxpQkFBaUIsb0JBQW9CLHdCQUF3QixpQkFBaUIsQ0FBQztBQUFBLElBQ3ZILGFBQWEsVUFBVSxDQUFDO0FBQUEsTUFDdEIsYUFBYSxzQ0FBc0Msc0JBQXNCLENBQUM7QUFBQSxzQ0FDMUMsdUJBQXVCLFlBQVksR0FBRyxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLG1CQU0xRCxtQkFBbUIsWUFBWSxXQUFXLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBUXRELGtCQUFrQixZQUFZLGNBQWMsUUFBUSxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxRQVFyRCxrQkFBa0IsWUFBWSxjQUFjLFFBQVEsQ0FBQztBQUFBO0FBQUEsUUFFckQsa0JBQWtCLFlBQVksY0FBYyxRQUFRLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQSxRQUkzRDtBQUNBLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWEsRUFBRSxNQUFNLEdBQUcsU0FBUyxJQUFJLGNBQWMsSUFBSSxrQkFBa0I7QUFBQSxVQUN6RSxZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxlQUFlLENBQUM7QUFBQSxZQUN6RCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxhQUFhO0FBQUE7QUFBQSxZQUF1QixFQUFFO0FBQUEsWUFDcEU7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxzQkFBc0IsQ0FBQyxTQUF5QixlQUFvRDtBQUMvRyxjQUFNLFNBQVNELGlCQUFlLFFBQVEsUUFBUSxVQUFVO0FBQ3hELFlBQUksUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLFdBQVcsR0FBRztBQUN2QyxnQkFBTSxJQUFJLE1BQU0sK0JBQStCO0FBQUEsUUFDakQ7QUFFQSxZQUFJLFFBQVEsT0FBTyxDQUFDLEdBQUcsS0FBSyxXQUFXLEdBQUc7QUFDeEMsZ0JBQU0sSUFBSSxNQUFNLDhCQUE4QjtBQUFBLFFBQ2hEO0FBRUEsY0FBTSxJQUFJLFFBQVEsT0FBTyxDQUFDO0FBQzFCLGNBQU0sSUFBSSxRQUFRLE9BQU8sQ0FBQyxLQUFLLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxTQUFTLElBQUksUUFBUSxPQUFPLENBQUMsSUFBSTtBQUN2RixjQUFNLElBQUksUUFBUSxPQUFPLENBQUMsS0FBSyxRQUFRLE9BQU8sQ0FBQyxFQUFFLEtBQUssU0FBUyxJQUFJLFFBQVEsT0FBTyxDQUFDLElBQUk7QUFDdkYsY0FBTSxVQUFVLFFBQVEsT0FBTyxDQUFDLEtBQUssUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLFdBQVcsSUFBSSxRQUFRLE9BQU8sQ0FBQyxJQUFJO0FBQy9GLGNBQU0sWUFBWSxRQUFRLE9BQU8sQ0FBQyxLQUFLLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLElBQUksUUFBUSxPQUFPLENBQUMsSUFBSTtBQUNqRyxjQUFNLFVBQVUsUUFBUSxPQUFPLFNBQVMsSUFBSSxRQUFRLE9BQU8sQ0FBQyxJQUFJO0FBQ2hFLGNBQU0sMkJBQTJCLFFBQVEsT0FBTyxTQUFTLElBQUksUUFBUSxPQUFPLENBQUMsSUFBSTtBQUNqRixjQUFNLGFBQWEsT0FBTyxhQUFhLE9BQU8sYUFBYSxPQUFPO0FBSWxFLGNBQU0sa0JBQW1DLDRCQUE0QjtBQUFBLFVBQ25FLE1BQU07QUFBQSxVQUNOLFlBQVk7QUFBQSxVQUNaLFlBQVksQ0FBQyxPQUFPLFdBQVcsT0FBTyxVQUFVLGFBQWEsT0FBTyxVQUFVLGFBQWEsT0FBTyxRQUFRO0FBQUEsUUFDNUcsQ0FBQztBQUNELGNBQU0sQ0FBQyxPQUFPLEtBQUssS0FBSyxJQUN0QixDQUFDLEtBQUssQ0FBQyxJQUNILFFBQVEsUUFBUSx1QkFBdUIsQ0FBQyxDQUFDLEdBQUcsZUFBZSxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsSUFBSSxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQ3BHLENBQUMsR0FBRyxHQUFJLENBQUU7QUFDaEIsWUFBSTtBQUNKLFlBQUk7QUFDSixZQUFJLFdBQVcsVUFBVTtBQUN2QixnQkFBTSxTQUFTLFFBQVE7QUFBQSxZQUNyQiwrQkFBK0IsT0FBTyxXQUFXLE9BQU8sZ0JBQWdCLFNBQVUsd0JBQXlCO0FBQUEsWUFDM0csRUFBRSxRQUFRLENBQUMsU0FBVSx3QkFBeUIsR0FBRyxTQUFTLENBQUMsRUFBRSxFQUFFO0FBQUEsVUFDakUsRUFBRSxDQUFDO0FBQ0gsZ0JBQU0sV0FBVyxRQUFRLE9BQU8sQ0FBQztBQUNqQyxnQkFBTSxXQUFXLFFBQVEsT0FBTyxDQUFDO0FBQ2pDLGdCQUFNLDZCQUF3RCw0QkFBNEI7QUFBQSxZQUN4RixhQUFhLFdBQVcsc0JBQXNCO0FBQUEsWUFDOUMsVUFBVSxPQUFPO0FBQUEsWUFDakIsb0JBQW9CO0FBQUEsWUFDcEIsT0FBTyxXQUFXO0FBQUEsVUFDcEIsQ0FBQztBQUNELGdCQUFNLFNBQVMsQ0FBQyxPQUFPLFFBQVEsVUFBVSxRQUFRO0FBQ2pELGdCQUFNLFVBQVUsQ0FBQyxFQUFFO0FBQ25CLG9CQUFVLFFBQVEsUUFBUSxpQ0FBaUMsUUFBUSwwQkFBMEIsR0FBRztBQUFBLFlBQzlGO0FBQUEsWUFDQTtBQUFBLFVBQ0YsQ0FBQyxFQUFFLENBQUM7QUFDSixpQkFBTyxPQUFPLEdBQUcsR0FBRyxHQUFHO0FBQ3ZCLGdCQUFNLDZCQUF3RCw0QkFBNEI7QUFBQSxZQUN4RixhQUFhLFdBQVcsc0JBQXNCO0FBQUEsWUFDOUMsVUFBVSxPQUFPO0FBQUEsWUFDakIsb0JBQW9CO0FBQUEsWUFDcEIsT0FBTyxXQUFXO0FBQUEsVUFDcEIsQ0FBQztBQUNELG9CQUFVLFFBQVEsUUFBUSxpQ0FBaUMsUUFBUSwwQkFBMEIsR0FBRztBQUFBLFlBQzlGO0FBQUEsWUFDQTtBQUFBLFVBQ0YsQ0FBQyxFQUFFLENBQUM7QUFBQSxRQUNOO0FBQ0EsY0FBTSxJQUFJO0FBQUEsVUFDUjtBQUFBLFVBQ0EsT0FBTztBQUFBLFVBQ1AsT0FBTztBQUFBLFVBQ1AsT0FBTztBQUFBLFVBQ1AsT0FBTztBQUFBLFVBQ1AsV0FBVyxXQUFXLFVBQVc7QUFBQSxVQUNqQztBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQ0EsY0FBTSxJQUFJLHFCQUFxQixTQUFTLFdBQVcsV0FBVyxVQUFXLEtBQUssTUFBTTtBQUNwRixjQUFNLElBQUkscUJBQXFCLFNBQVMsT0FBTyxNQUFNO0FBRXJEO0FBQUEsVUFDRTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFBQTtBQUFBOzs7QUNwWkEsTUF3Qk0sMEJBbUZBLCtCQWlFQSxtQ0FnR087QUE1UWI7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUVBO0FBRUE7QUFlQSxNQUFNLDJCQUEyQixDQUMvQixTQUNBLE9BQ0EsT0FDQSxNQUNBLEdBQ0EsR0FDQSxHQUNBLFlBQ0c7QUFDSCxjQUFNLGFBQWEsaUJBQWlCLENBQUM7QUFDckMsY0FBTSxVQUFVLGVBQWUsSUFBSSxRQUFRLE1BQU0sVUFBVTtBQUMzRCxjQUFNLFNBQVMsZUFBZSxJQUFJLFVBQVUsUUFBUSxVQUFVO0FBQzlELGNBQU0sY0FBYyxJQUFJO0FBQ3hCLFlBQUksZ0JBQWdCO0FBQ3BCLFlBQUksZ0JBQWdCLEdBQUc7QUFDckIsMEJBQWdCO0FBQUEsUUFDbEI7QUFDQSxjQUFNLGFBQWEsQ0FBQyxHQUFHLEdBQUcsSUFBSSxVQUFVO0FBQ3hDLGNBQU0sY0FBYyxDQUFDLEdBQUcsR0FBRyxDQUFDO0FBQzVCLGNBQU0sb0JBQXdELENBQUMsUUFBUSxRQUFRLE1BQU07QUFDckYsY0FBTSxrQkFBb0MsQ0FBQztBQUMzQyx3QkFBZ0IsS0FBSyxHQUFHLDJCQUEyQixZQUFZLFdBQVcsQ0FBQztBQUUzRSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxnQkFBTSxJQUFJLGNBQWMsS0FBSyxNQUFNLFVBQVUsR0FBRyxVQUFVO0FBQzFELGdCQUFNLElBQUksY0FBYyxTQUFTLE1BQU0sVUFBVSxNQUFNLElBQUk7QUFDM0QsZ0JBQU0sSUFBSSxjQUFjLFFBQVEsS0FBSyxVQUFVLEtBQUssSUFBSTtBQUN4RCxnQkFBTSxTQUFTLGVBQWUseUJBQTBCLEdBQUcsQ0FBQztBQUM1RCxnQkFBTSxZQUFZLENBQUMsR0FBRyxHQUFHLEdBQUcsTUFBTTtBQUNsQyxpQkFBTztBQUFBLDRDQUNpQyxNQUFNLEtBQUssYUFBYTtBQUFBLDJCQUN6QyxhQUFhO0FBQUEsSUFDcEMsYUFBYSxpQkFBaUIsR0FBRyxTQUFTLENBQUM7QUFBQSxJQUMzQyxhQUFhLFVBQVUsYUFBYSxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFLekIsT0FBTztBQUFBLHdCQUNDLE9BQU87QUFBQTtBQUFBLG9CQUVYLE9BQU8sSUFBSSxFQUFFLElBQUksU0FBUyxXQUFXLEdBQUcsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBLG9DQUl6QixNQUFNO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsd0JBVWxCLFVBQVUsMEJBQTBCLFVBQVUsQ0FBQyxrQkFBa0IsVUFBVTtBQUFBLGdDQUNuRSxVQUFVLDBCQUEwQixVQUFVLENBQUMsa0JBQWtCLFVBQVU7QUFBQTtBQUFBLHNGQUVyQixPQUFPO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBTTNGO0FBRUEsZUFBTyxRQUFRO0FBQUEsVUFDYjtBQUFBLFlBQ0UsTUFBTTtBQUFBO0FBQUEsWUFFTixhQUFhLEVBQUUsTUFBTSxHQUFHLFVBQVUsSUFBSSxPQUFPLElBQUksYUFBYSxJQUFJLGtCQUFrQjtBQUFBLFlBQ3BGLFlBQVksT0FBTztBQUFBLGNBQ2pCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sYUFBYSx3QkFBeUIsQ0FBQztBQUFBLGNBQ3pELGVBQWUsRUFBRSxHQUFHLFlBQVk7QUFBQSxjQUNoQztBQUFBLFlBQ0Y7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUFBLFVBQ0EsRUFBRSxRQUFRLENBQUMsT0FBTyxPQUFPLElBQUksR0FBRyxTQUFTLENBQUMsRUFBRSxFQUFFO0FBQUEsUUFDaEQsRUFBRSxDQUFDO0FBQUEsTUFDTDtBQUVBLE1BQU0sZ0NBQWdDLENBQ3BDLFNBQ0EsUUFDQSxlQUNHO0FBQ0gsY0FBTSxTQUFTLE9BQU8sQ0FBQyxFQUFFO0FBQ3pCLGNBQU0sY0FBYztBQUNwQixjQUFNLE9BQU87QUFDYixjQUFNLElBQUksT0FBTyxDQUFDO0FBQ2xCLGNBQU0sSUFBSSxPQUFPLENBQUM7QUFDbEIsY0FBTSxJQUFJLFVBQVUsa0JBQWtCLFFBQVEsSUFBSTtBQUNsRCxjQUFNLGFBQWEsaUJBQWlCLENBQUM7QUFDckMsY0FBTSxhQUFhLFVBQVUsS0FBSyxXQUFXLElBQUk7QUFFakQsY0FBTSxvQkFBb0I7QUFBQSxVQUN4QjtBQUFBLFVBQ0EsT0FBTyxDQUFDO0FBQUEsVUFDUixPQUFPLENBQUM7QUFBQSxVQUNSLE9BQU8sQ0FBQztBQUFBLFVBQ1I7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0EsV0FBVztBQUFBLFFBQ2I7QUFFQSxjQUFNLGFBQWEsQ0FBQyxHQUFHLEdBQUcsSUFBSSxVQUFVO0FBQ3hDLGNBQU0sYUFBYSxDQUFDLEdBQUcsQ0FBQztBQUN4QixjQUFNLG9CQUF3RCxDQUFDLFFBQVEsTUFBTTtBQUU3RSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxnQkFBTSxJQUFJLGNBQWMsS0FBSyxPQUFPLENBQUMsRUFBRSxVQUFVLFdBQVcsUUFBUSxVQUFVO0FBQzlFLGdCQUFNLFFBQVEsY0FBYyw4QkFBK0IsV0FBVyxRQUFRLENBQUM7QUFDL0UsZ0JBQU0sU0FBUyxlQUFlLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxXQUFXLFFBQVEsVUFBVTtBQUN6RixnQkFBTSxZQUFZLENBQUMsR0FBRyxPQUFPLE1BQU07QUFDbkMsaUJBQU87QUFBQSxJQUNQLGFBQWEsZ0JBQWdCLGVBQWUsS0FBSyxFQUFFLGlCQUFpQixHQUFHLFNBQVMsQ0FBQztBQUFBLElBQ2pGLGFBQWEsVUFBVSxDQUFDO0FBQUEsSUFDeEIsYUFBYSxzQ0FBc0Msc0JBQXNCLENBQUM7QUFBQSw0QkFDbEQsT0FBTyxnQkFBZ0IsWUFBWSxDQUFDO0FBQUE7QUFBQTtBQUFBLDBCQUd0QyxNQUFNLGFBQWEsMkJBQTJCLENBQUM7QUFBQSxvQkFDckQsRUFBRSxZQUFZLFlBQVksQ0FBQyxNQUFNLE9BQU8sS0FBSyxLQUFLLHFCQUFxQixPQUFPLEtBQUssS0FBSztBQUFBLFFBQ3BHLE9BQU8sWUFBWSxjQUFjLE9BQU8sQ0FBQztBQUFBO0FBQUEsUUFFL0M7QUFFQSxnQkFBUTtBQUFBLFVBQ047QUFBQSxZQUNFLE1BQU07QUFBQSxZQUNOLGFBQWEsRUFBRSxNQUFNLEdBQUcsVUFBVSxJQUFJLGtCQUFrQjtBQUFBLFlBQ3hELFlBQVksT0FBTztBQUFBLGNBQ2pCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sYUFBYSxVQUFVLE9BQU8sQ0FBQyxFQUFFLFNBQVMsQ0FBQztBQUFBLGNBQzdELGVBQWUsRUFBRSxHQUFHLEtBQUs7QUFBQSxnQkFBSyxhQUFhO0FBQUE7QUFBQSxjQUF1QixFQUFFO0FBQUEsY0FDcEUsaUJBQWlCO0FBQUEsZ0JBQ2YsRUFBRSx1QkFBdUIsTUFBTSxXQUFXO0FBQUEsZ0JBQzFDLEdBQUcsMkJBQTJCLFlBQVksWUFBWSxVQUFVO0FBQUEsY0FDbEU7QUFBQSxZQUNGO0FBQUEsWUFDQTtBQUFBLFVBQ0Y7QUFBQSxVQUNBLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLGlCQUFpQixFQUFFO0FBQUEsUUFDM0M7QUFBQSxNQUNGO0FBRUEsTUFBTSxvQ0FBb0MsQ0FDeEMsU0FDQSxRQUNBLGVBQ0c7QUFDSCxjQUFNLFNBQVMsT0FBTyxDQUFDLEVBQUU7QUFDekIsY0FBTSxjQUFjO0FBQ3BCLGNBQU0sSUFBSSxPQUFPLENBQUM7QUFDbEIsY0FBTSxJQUFJLE9BQU8sT0FBTyxTQUFTLENBQUM7QUFDbEMsY0FBTSxJQUFJLFVBQVUsa0JBQWtCLFFBQVEsQ0FBQyxJQUFJO0FBQ25ELGNBQU0sYUFBYSxpQkFBaUIsQ0FBQztBQUNyQyxjQUFNLGFBQWEsVUFBVSxLQUFLLFdBQVcsSUFBSTtBQUNqRCxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sRUFBRTtBQUFBLFVBQ2pDLEVBQUUsdUJBQXVCLE1BQU0sS0FBSyxNQUFNLElBQUksVUFBVSxFQUFFO0FBQUEsUUFDNUQ7QUFDQSxjQUFNLG9CQUF3RCxDQUFDLFFBQVEsTUFBTTtBQUc3RSxZQUFJLGdCQUFnQjtBQUNwQixjQUFNLGtCQUFrQixDQUFDLEdBQUcsT0FBTyxTQUFTLENBQUM7QUFDN0MsaUJBQVMsSUFBSSxHQUFHLElBQUksT0FBTyxTQUFTLEdBQUcsS0FBSztBQUMxQywwQkFBZ0IsaUJBQWlCLE9BQU8sSUFBSSxDQUFDLE1BQU07QUFDbkQsMEJBQWdCLEtBQUssSUFBSSxDQUFDO0FBQUEsUUFDNUI7QUFFQSx3QkFBZ0IsaUJBQWlCLE9BQU8sT0FBTyxTQUFTLENBQUMsTUFBTTtBQUUvRCxjQUFNLGNBQWMsZ0JBQ2hCLFFBQVEsUUFBUSwyQkFBMkIsUUFBUSxPQUFPLENBQUMsR0FBRyxlQUFlLEdBQUc7QUFBQSxVQUM5RSxRQUFRLENBQUMsUUFBUSxPQUFPLENBQUMsQ0FBQztBQUFBLFVBQzFCLFNBQVMsQ0FBQyxFQUFFO0FBQUEsUUFDZCxDQUFDLEVBQUUsQ0FBQyxJQUNKLFFBQVEsT0FBTyxDQUFDLEVBQUUsUUFBUSxNQUFNLEtBQUssRUFBRSxRQUFRLE9BQU8sT0FBTyxHQUFHLENBQUMsR0FBRyxNQUFNLE9BQU8sZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFekcsY0FBTSxvQkFBb0I7QUFBQSxVQUN4QjtBQUFBLFVBQ0E7QUFBQSxVQUNBLE9BQU8sQ0FBQztBQUFBLFVBQ1IsT0FBTyxDQUFDO0FBQUEsVUFDUjtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQSxXQUFXO0FBQUEsUUFDYjtBQUNBLGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQ3RELGdCQUFNLFdBQVcsNEJBQTRCLE9BQU8sQ0FBQyxFQUFFLFFBQVE7QUFDL0QsZ0JBQU0sWUFBWSxlQUFlLElBQUksVUFBVSxNQUFNLFVBQVU7QUFDL0QsZ0JBQU0sWUFBWSxDQUFDLFFBQWdCO0FBQ2pDLGtCQUFNLFFBQVEsUUFBUSxJQUFJLE1BQU07QUFDaEMsa0JBQU0sVUFBVSxlQUFlLElBQUksUUFBUSxNQUFNLFVBQVU7QUFDM0Qsb0JBQVEsWUFBWTtBQUFBLGNBQ2xCLEtBQUs7QUFDSCx1QkFBTyxHQUFHLFFBQVEsSUFBSSxPQUFPLFVBQVUsS0FBSztBQUFBLGNBQzlDLEtBQUs7QUFDSCx1QkFBTyxRQUFRLFFBQVEsS0FBSyxPQUFPLGFBQWEsS0FBSyxjQUFjLEtBQUs7QUFBQSxjQUMxRSxLQUFLO0FBQ0gsdUJBQU8sUUFBUSxRQUFRLEtBQUssT0FBTyxhQUFhLEtBQUssY0FBYyxLQUFLLGNBQWMsS0FBSyxjQUFjLEtBQUs7QUFBQSxjQUNoSDtBQUNFLHNCQUFNLElBQUksTUFBTSwyQkFBMkIsVUFBVSxFQUFFO0FBQUEsWUFDM0Q7QUFBQSxVQUNGO0FBQ0EsZ0JBQU0sY0FBYyxjQUFjLFNBQVMsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxNQUFNLFVBQVU7QUFDekYsZ0JBQU0sZUFBZSxlQUFlLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxhQUFhLFVBQVU7QUFFekYsaUJBQU87QUFBQSwyREFDZ0QsWUFBWSxLQUFLLE9BQU87QUFBQSxpRUFDbEIsU0FBUztBQUFBLGtFQUNSLGFBQWEsS0FBSyxPQUFPO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFJdkYsYUFBYSxVQUFVLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsa0RBTXNCLFVBQVUsQ0FBQyxDQUFDLEtBQUssVUFBVSxDQUFDLENBQUM7QUFBQTtBQUFBLFFBRTdFO0FBQ0EsZ0JBQVE7QUFBQSxVQUNOO0FBQUEsWUFDRSxNQUFNO0FBQUEsWUFDTixhQUFhLEVBQUUsTUFBTSxHQUFHLFVBQVUsSUFBSSxrQkFBa0I7QUFBQSxZQUN4RCxZQUFZLE9BQU87QUFBQSxjQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxPQUFPLENBQUMsRUFBRSxTQUFTLENBQUM7QUFBQSxjQUM3RCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsZ0JBQUssYUFBYTtBQUFBO0FBQUEsY0FBdUIsRUFBRTtBQUFBLGNBQ3BFO0FBQUEsWUFDRjtBQUFBLFlBQ0E7QUFBQSxVQUNGO0FBQUEsVUFDQSxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxpQkFBaUIsRUFBRTtBQUFBLFFBQzNDO0FBQUEsTUFDRjtBQUVPLE1BQU0sZUFBZSxDQUFDLFNBQXlCLGVBQTZDO0FBQ2pHLFlBQUksV0FBVyxXQUFXLFFBQVE7QUFDaEMsNENBQWtDLFNBQVMsUUFBUSxRQUFRLFVBQVU7QUFBQSxRQUN2RSxPQUFPO0FBQ0wsd0NBQThCLFNBQVMsUUFBUSxRQUFRLFVBQVU7QUFBQSxRQUNuRTtBQUFBLE1BQ0Y7QUFBQTtBQUFBOzs7QUNsUkEsTUEwQk1FLGtCQU1BLDRCQXVITztBQXZKYjtBQUFBO0FBQUE7QUFHQTtBQUVBO0FBR0E7QUFrQkEsTUFBTUEsbUJBQWlCLENBQUMsV0FBd0M7QUFDOUQsWUFBSSxDQUFDLFVBQVUsT0FBTyxTQUFTLEdBQUc7QUFDaEMsZ0JBQU0sSUFBSSxNQUFNLHVDQUF1QztBQUFBLFFBQ3pEO0FBQUEsTUFDRjtBQUVBLE1BQU0sNkJBQTZCLENBQ2pDLFFBQ0EsWUFDQSxnQkFDZ0I7QUFDaEIsY0FBTSxhQUFhLFdBQVc7QUFFOUIsY0FBTSxTQUFTLE9BQU8sQ0FBQyxFQUFFO0FBQ3pCLGNBQU0sUUFBUSxPQUFPLENBQUM7QUFDdEIsY0FBTSxPQUFPLENBQUMsY0FBYyxPQUFPLENBQUM7QUFFcEMsY0FBTSxjQUFjO0FBQ3BCLGNBQU0sT0FBTyxVQUFVLGNBQWMsV0FBVyxNQUFNLE9BQU8sTUFBTTtBQUNuRSxjQUFNLFlBQVksVUFBVSxnQkFBZ0IsUUFBUSxJQUFJO0FBQ3hELGNBQU0sV0FBVyxVQUFVLGtCQUFrQixRQUFRLElBQUk7QUFFekQsY0FBTSxZQUFZLFVBQVUsS0FBSyxNQUFNLElBQUk7QUFDM0MsY0FBTSxXQUFXLE9BQU8sVUFBVSxLQUFLLEtBQUssSUFBSSxJQUFJO0FBQ3BELFlBQUksY0FBYyxZQUFhLFFBQVEsYUFBYSxVQUFXO0FBQzdELGdCQUFNLElBQUksTUFBTSwrQkFBK0IsUUFBUTtBQUFBO0FBQUEsMkJBRWhDLFNBQVMscUJBQXFCLFFBQVEsRUFBRTtBQUFBLFFBQ2pFO0FBRUEsY0FBTSxtQkFBNkIsQ0FBQztBQUNwQyxpQkFBUyxJQUFJLEdBQUcsSUFBSSxPQUFPLFFBQVEsRUFBRSxHQUFHO0FBQ3RDLGNBQUksSUFBSSxNQUFNO0FBQ1osNkJBQWlCLEtBQUssT0FBTyxDQUFDLENBQUM7QUFBQSxVQUNqQyxPQUFPO0FBQ0wsNkJBQWlCLEtBQUssQ0FBQztBQUFBLFVBQ3pCO0FBQUEsUUFDRjtBQUNBLGNBQU0sYUFBYSxpQkFBaUIsUUFBUTtBQUM1QyxjQUFNLG9CQUF3RCxDQUFDLFFBQVEsTUFBTTtBQUM3RSxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sVUFBVTtBQUFBLFVBQ3pDLEVBQUUscUJBQXNCLE1BQU0sU0FBUztBQUFBLFVBQ3ZDLEVBQUUsdUJBQXVCLE1BQU0sS0FBSyxNQUFNLFdBQVcsVUFBVSxFQUFFO0FBQUEsVUFDakUsRUFBRSxxQkFBc0IsTUFBTSxXQUFXLFFBQVE7QUFBQSxRQUNuRDtBQUNBLFlBQUksTUFBTTtBQUNSLDRCQUFrQixLQUFLLE1BQU07QUFBQSxRQUMvQjtBQUNBLGNBQU0sb0JBQW9CLGNBQWM7QUFDeEMsY0FBTSxrQkFBa0IsY0FBYztBQUV0QyxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxnQkFBTSxXQUFXLDRCQUE0QixPQUFPLENBQUMsRUFBRSxRQUFRO0FBQy9ELGdCQUFNLFlBQVk7QUFBQSxZQUNoQixjQUFjLEtBQUssT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxNQUFNLFVBQVU7QUFBQSxZQUNqRSxjQUFjLFNBQVMsTUFBTSxVQUFVLE1BQU0sTUFBTSxVQUFVO0FBQUEsVUFDL0Q7QUFDQSxjQUFJLE1BQU07QUFDUixzQkFBVSxLQUFLLGNBQWMsUUFBUSxLQUFLLFVBQVUsS0FBSyxNQUFNLFVBQVUsQ0FBQztBQUFBLFVBQzVFO0FBQ0Esb0JBQVUsS0FBSyxlQUFlLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxhQUFhLFVBQVUsQ0FBQztBQUNwRixjQUFJLG1CQUFtQjtBQUNyQixzQkFBVSxLQUFLLGVBQWUsbUNBQW9DLGdCQUFnQixDQUFDO0FBQUEsVUFDckY7QUFDQSxjQUFJLGlCQUFpQjtBQUNuQixzQkFBVSxLQUFLLGVBQWUsaUNBQWtDLGdCQUFnQixDQUFDO0FBQUEsVUFDbkY7QUFFQSxnQkFBTSxXQUE4QjtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxjQUFjLE1BQU0sTUFBTTtBQUFBLFlBQ2xDLEVBQUUsTUFBTSxhQUFhLE1BQU0sTUFBTTtBQUFBLFlBQ2pDLEVBQUUsTUFBTSx3QkFBd0IsTUFBTSxNQUFNO0FBQUEsWUFDNUMsRUFBRSxNQUFNLFdBQVcsTUFBTSxNQUFNO0FBQUEsVUFDakM7QUFDQSxpQkFBTztBQUFBLElBQ1AsYUFBYSxpQkFBaUIsUUFBUSxFQUFFLGlCQUFpQixHQUFHLFNBQVMsQ0FBQztBQUFBLElBQ3RFLGFBQWEsVUFBVSxDQUFDO0FBQUEsTUFDdEIsYUFBYSxzQ0FBc0MscUJBQXFCLENBQUM7QUFBQTtBQUFBLHdCQUV2RCxXQUFXLE9BQU8sVUFBVSxDQUFDO0FBQUEsK0JBQ3RCLFdBQVcsT0FBTyxVQUFVLENBQUM7QUFBQTtBQUFBO0FBQUEsb0JBR3hDLFVBQVUsVUFBVSxZQUFZLGVBQWUsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBLGlCQUluRCxVQUFVLGVBQWUsVUFBVSxDQUFDO0FBQUEsb0NBQ2pCLFVBQVUsc0JBQXNCLFVBQVUsQ0FBQyx5QkFDekUsYUFBYSxLQUFLLGVBQ3BCO0FBQUE7QUFBQTtBQUFBLHVCQUdtQixVQUFVLFVBQVUsWUFBWSxlQUFlLENBQUM7QUFBQSx1QkFDaEQsVUFBVSxVQUFVLFlBQVksVUFBVSxDQUFDO0FBQUEsNkJBQ3JDLFVBQVUsQ0FBQyxFQUFFLEtBQUssS0FBSyxjQUFjLGFBQWEsS0FBSyxRQUFRO0FBQUEsVUFDbEYsT0FBTyxLQUFLLFVBQVUsVUFBVSxZQUFZLFNBQVMsQ0FBQyxLQUFLLEVBQUU7QUFBQTtBQUFBO0FBQUE7QUFBQSxNQUlqRSxvQkFBb0Isd0NBQXdDLEVBQUU7QUFBQSxNQUM5RCxrQkFBa0IsNkNBQTZDLEVBQUU7QUFBQTtBQUFBLFFBRXJFO0FBQ0EsY0FBTSxVQUFVLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxPQUFPLENBQUMsRUFBRSxTQUFTLENBQUM7QUFDcEUsWUFBSSxtQkFBbUI7QUFDckIsa0JBQVEsS0FBSyxFQUFFLE1BQU0sa0JBQWtCLHdCQUF5QixDQUFDO0FBQUEsUUFDbkU7QUFDQSxZQUFJLGlCQUFpQjtBQUNuQixrQkFBUSxLQUFLLEVBQUUsTUFBTSxrQkFBa0Isd0JBQXlCLENBQUM7QUFBQSxRQUNuRTtBQUVBLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWEsRUFBRSxNQUFNLEdBQUcsVUFBVSxJQUFJLFdBQVcsSUFBSSxVQUFVLElBQUksa0JBQWtCO0FBQUEsVUFDckYsWUFBWSxPQUFPO0FBQUEsWUFDakI7QUFBQSxZQUNBLGVBQWUsRUFBRSxHQUFHLEtBQUs7QUFBQSxjQUFLLFlBQVk7QUFBQTtBQUFBLFlBQXVCLEVBQUU7QUFBQSxZQUNuRTtBQUFBLFVBQ0Y7QUFBQSxVQUNBO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLFlBQVksQ0FBQyxTQUF5QixlQUEwQztBQUMzRixRQUFBQSxpQkFBZSxRQUFRLE1BQU07QUFDN0IsZ0JBQVEsUUFBUSwyQkFBMkIsUUFBUSxRQUFRLFlBQVksUUFBUSxXQUFXLENBQUM7QUFBQSxNQUM3RjtBQUFBO0FBQUE7OztBQzFKQSxNQVVNQyxrQkFVTztBQXBCYjtBQUFBO0FBQUE7QUFJQTtBQUdBO0FBQ0E7QUFFQSxNQUFNQSxtQkFBaUIsQ0FBQyxXQUF3QztBQUM5RCxZQUFJLENBQUMsVUFBVSxPQUFPLFdBQVcsR0FBRztBQUNsQyxnQkFBTSxJQUFJLE1BQU0sMkJBQTJCO0FBQUEsUUFDN0M7QUFFQSxZQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssT0FBTyxDQUFDLEVBQUUsS0FBSyxTQUFTLENBQUMsTUFBTSxPQUFPLENBQUMsRUFBRSxLQUFLLE9BQU8sQ0FBQyxFQUFFLEtBQUssU0FBUyxDQUFDLEdBQUc7QUFDM0YsZ0JBQU0sSUFBSSxNQUFNLGtDQUFrQztBQUFBLFFBQ3BEO0FBQUEsTUFDRjtBQUVPLE1BQU0sU0FBUyxDQUFDLFlBQWtDO0FBQ3ZELFFBQUFBLGlCQUFlLFFBQVEsTUFBTTtBQUM3QixjQUFNLGNBQWMsY0FBYyxVQUFVLFFBQVEsT0FBTyxDQUFDLEVBQUUsTUFBTSxRQUFRLE9BQU8sQ0FBQyxFQUFFLE1BQU0sSUFBSTtBQUNoRyxZQUFJLENBQUMsYUFBYTtBQUNoQixnQkFBTSxJQUFJLE1BQU0sdUNBQXVDO0FBQUEsUUFDekQ7QUFDQSxjQUFNLElBQUksWUFBWSxZQUFZLFNBQVMsQ0FBQztBQUM1QyxjQUFNLElBQUksUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLFFBQVEsT0FBTyxDQUFDLEVBQUUsS0FBSyxTQUFTLENBQUM7QUFDbEUsWUFBSSxJQUFJLEtBQUssSUFBSSxHQUFHO0FBQ2xCLGtCQUFRLFFBQVEsNkJBQTZCLFFBQVEsUUFBUSxFQUFFLFlBQVksR0FBRyxHQUFHLFdBQVcsQ0FBQztBQUFBLFFBQy9GLE9BQU87QUFDTCxnQkFBTSxJQUFJLFlBQVksWUFBWSxTQUFTLENBQUM7QUFDNUMsZ0JBQU0sU0FBUyxVQUFVLEtBQUssUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU0sR0FBRyxFQUFFLENBQUM7QUFDakUsZ0JBQU0sU0FBUyxVQUFVLEtBQUssUUFBUSxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU0sR0FBRyxFQUFFLENBQUM7QUFDakUsY0FBSSxXQUFXLEtBQUssTUFBTSxLQUFLLFdBQVcsR0FBRztBQUUzQyxrQkFBTSxZQUFZLFFBQVEsT0FBTyxDQUFDLEVBQUUsUUFBUSxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUM7QUFDMUQsa0JBQU0sWUFBWSxRQUFRLE9BQU8sQ0FBQyxFQUFFLFFBQVEsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0FBQ3JELGtCQUFNLG9CQUFvQixDQUFDLEdBQUcsUUFBUSxDQUFDO0FBQ3ZDLGtCQUFNLGVBQWUsQ0FBQyxXQUFXLFNBQVM7QUFDMUMsb0JBQVEsUUFBUSx3QkFBd0IsY0FBYyxFQUFFLFlBQVksR0FBRyxHQUFHLGFBQWEsaUJBQWlCLEdBQUc7QUFBQSxjQUN6RyxRQUFRO0FBQUEsWUFDVixDQUFDO0FBQUEsVUFDSCxPQUFPO0FBQ0wsb0JBQVEsUUFBUSx3QkFBd0IsUUFBUSxRQUFRLEVBQUUsWUFBWSxHQUFHLEdBQUcsV0FBVyxDQUFDO0FBQUEsVUFDMUY7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQy9DQSxNQTJCTUMsa0JBK0JPLDhCQW1OQSx5Q0F1S0EsYUFhQTtBQWpjYjtBQUFBO0FBQUE7QUFHQTtBQUVBO0FBQ0E7QUFHQTtBQWtCQSxNQUFNQSxtQkFBaUIsQ0FBQyxRQUErQixlQUE0QztBQUNqRyxZQUFJLE9BQU8sU0FBUyxLQUFLLE9BQU8sU0FBUyxHQUFHO0FBQzFDLGdCQUFNLElBQUksTUFBTSxvQ0FBb0M7QUFBQSxRQUN0RDtBQUNBLGNBQU0sSUFBSSxPQUFPLENBQUM7QUFDbEIsY0FBTSxRQUFRLEVBQUUsS0FBSztBQUNyQixZQUFJLEVBQUUsS0FBSyxRQUFRLENBQUMsTUFBTSxXQUFXLEdBQUc7QUFDdEMsZ0JBQU0sSUFBSSxNQUFNLHdEQUF3RDtBQUFBLFFBQzFFO0FBQ0EsY0FBTSxnQkFBZ0IsS0FBSyxPQUFPLFdBQVcsSUFBSSxXQUFXLFlBQVksS0FBSyxXQUFXLFNBQVM7QUFDakcsY0FBTSxXQUFZLFdBQVcsWUFBWSxJQUFLLFdBQVc7QUFDekQsY0FBTSxJQUFJLE9BQU8sQ0FBQztBQUNsQixZQUFJLENBQUMsVUFBVSxTQUFTLEVBQUUsTUFBTSxDQUFDLFdBQVcsR0FBRyxlQUFlLFFBQVEsQ0FBQyxHQUFHO0FBQ3hFLGdCQUFNLElBQUksTUFBTSw2RUFBNkU7QUFBQSxRQUMvRjtBQUNBLGNBQU0sU0FBUyxPQUFPLENBQUM7QUFDdkIsY0FBTSxjQUFjLE9BQU87QUFDM0IsWUFBSSxVQUFVLEtBQUssV0FBVyxNQUFNLFdBQVcsSUFBSSxlQUFlO0FBQ2hFLGdCQUFNLElBQUksTUFBTSwwQkFBMEI7QUFBQSxRQUM1QztBQUNBLFlBQUksT0FBTyxXQUFXLEdBQUc7QUFDdkIsZ0JBQU0sYUFBYSxPQUFPLENBQUM7QUFDM0IsZ0JBQU0sa0JBQWtCLFdBQVc7QUFDbkMsZ0JBQU0seUJBQ0osV0FBVyxPQUFPLElBQUksV0FBVyxJQUFJLGdCQUFnQixXQUFXLElBQUksS0FBSyxPQUFPLGdCQUFnQixLQUFLLENBQUM7QUFDeEcsY0FBSSxVQUFVLEtBQUssZUFBZSxNQUFNLHdCQUF3QjtBQUM5RCxrQkFBTSxJQUFJLE1BQU0sOEJBQThCO0FBQUEsVUFDaEQ7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sK0JBQStCLENBQzFDLFFBQ0EsZUFDZ0I7QUFDaEIsY0FBTSxhQUFhLE9BQU8sQ0FBQyxFQUFFO0FBQzdCLGNBQU0sUUFBUSxXQUFXO0FBQ3pCLGNBQU0sWUFBWSxXQUFXLFFBQVEsQ0FBQztBQUN0QyxjQUFNLFdBQVcsV0FBVztBQUM1QixjQUFNLFlBQVksV0FBVztBQUM3QixjQUFNLFlBQVksV0FBVyxNQUFNLEdBQUcsUUFBUSxDQUFDO0FBQy9DLGNBQU0sWUFBWSxVQUFVLEtBQUssU0FBUztBQUMxQyxjQUFNLFdBQVcsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDO0FBQ2pDLGNBQU0sa0JBQWtCLFdBQVc7QUFDbkMsY0FBTSxXQUFXLE9BQU8sQ0FBQyxFQUFFO0FBQzNCLGNBQU0sY0FBYyxpQkFBaUIsV0FBVyxDQUFDO0FBQ2pELGNBQU0sY0FBYyxpQkFBaUIsZUFBZTtBQUNwRCxjQUFNLGFBQWEsaUJBQWlCLFNBQVM7QUFDN0MsY0FBTSxjQUFjLFVBQVUsT0FBTyxDQUFDLFdBQVcsU0FBUyxDQUFDO0FBQzNELGNBQU0sZUFBZSxZQUFZLEtBQU0sWUFBWSxhQUFjLE1BQU0sSUFBSSxJQUFJO0FBQy9FLGNBQU0sZUFBZSxVQUFVLEtBQUssV0FBVyxJQUFJLGFBQWE7QUFFaEUsY0FBTSxnQkFBZ0I7QUFFdEIsY0FBTSxrQkFBb0MsQ0FBQztBQUMzQyxjQUFNLGlCQUFpQixDQUFDLFdBQVcsV0FBVyxXQUFXLFdBQVc7QUFDcEUsY0FBTSxTQUFTLFVBQVUsYUFBYSxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTTtBQUM1RCxlQUFPLE9BQU8sSUFBSSxHQUFHLGtCQUFrQixXQUFXO0FBQ2xELHdCQUFnQixLQUFLLEdBQUcsMkJBQTJCLGNBQWMsQ0FBQztBQUNsRSx3QkFBZ0IsS0FBSyxHQUFHLDJCQUEyQixNQUFNLENBQUM7QUFDMUQsd0JBQWdCLEtBQUssR0FBRywyQkFBMkIsT0FBTyxDQUFDLEVBQUUsSUFBSSxDQUFDO0FBQ2xFLFlBQUksT0FBTyxXQUFXLEdBQUc7QUFDdkIsMEJBQWdCLEtBQUssR0FBRywyQkFBMkIsVUFBVSxhQUFhLE9BQU8sQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQUEsUUFDNUY7QUFDQSxjQUFNLGtCQUFrQixDQUFDLFdBQVcsV0FBVyxZQUFZLFVBQVU7QUFDckUsd0JBQWdCLEtBQUssR0FBRywyQkFBMkIsZUFBZSxDQUFDO0FBRW5FLGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQ3RELGdCQUFNLFlBQVksZUFBZTtBQUNqQyxnQkFBTSxJQUFJLGNBQWMsS0FBSyxPQUFPLENBQUMsRUFBRSxVQUFVLFdBQVcsV0FBVztBQUN2RSxnQkFBTSxJQUFJLGNBQWMsc0JBQXNCLE9BQU8sUUFBUSxXQUFXO0FBQ3hFLGdCQUFNLFNBQVMsY0FBYyxVQUFVLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxDQUFDLEVBQUUsS0FBSyxNQUFNO0FBQ2hGLGdCQUFNLGlCQUFpQixDQUFDLEdBQUcsR0FBRyxNQUFNO0FBQ3BDLGdCQUFNLGFBQ0osT0FBTyxXQUFXLElBQUksY0FBYyxnQ0FBZ0MsT0FBTyxDQUFDLEVBQUUsS0FBSyxNQUFNLElBQUk7QUFDL0YsY0FBSSxZQUFZO0FBQ2QsMkJBQWUsS0FBSyxVQUFVO0FBQUEsVUFDaEM7QUFDQSxnQkFBTSxhQUFhLGdCQUFnQjtBQUNuQyxnQkFBTSxTQUFTLGVBQWUsVUFBVSxPQUFPLENBQUMsRUFBRSxVQUFVLFlBQVksVUFBVTtBQUNsRixnQkFBTUMsWUFBVyw0QkFBNEIsT0FBTyxDQUFDLEVBQUUsUUFBUTtBQUUvRCxnQkFBTSxlQUFlLE1BQU07QUFDekIsb0JBQVEsYUFBYTtBQUFBLGNBQ25CLEtBQUs7QUFDSCx1QkFBTyxTQUFTQSxTQUFRO0FBQUEsY0FDMUIsS0FBSztBQUNILHVCQUFPLFVBQVVBLFNBQVE7QUFBQSxjQUMzQixLQUFLO0FBQ0gsdUJBQU8sVUFBVUEsU0FBUTtBQUFBLGNBQzNCO0FBQ0Usc0JBQU0sSUFBSSxNQUFNLEdBQUcsV0FBVyw4QkFBOEI7QUFBQSxZQUNoRTtBQUFBLFVBQ0YsR0FBRztBQUVILGdCQUFNLGlCQUFpQixNQUFjO0FBQ25DLGdCQUFJLFVBQVU7QUFBQTtBQUFBLGlDQUVhLEVBQUUsZ0JBQWdCLEdBQUcsRUFBRSxLQUFLLE9BQU8sMkJBQTJCLENBQUM7QUFBQSwwQkFDdEUsV0FBVztBQUFBLHVDQUNFLElBQUksV0FBVztBQUFBLDRCQUMxQixFQUFFLFlBQVksY0FBYyxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBSW5ELHFCQUFTLElBQUksR0FBRyxJQUFJLGFBQWEsY0FBYyxLQUFLO0FBQ2xELHlCQUFXO0FBQUEsd0JBQ0ssZ0JBQWdCLElBQUksSUFBSSxDQUFDLFVBQVUsSUFBSSxDQUFDLFVBQVU7QUFBQTtBQUFBO0FBQUEsbUNBR3ZDLFdBQVcsSUFBSSxNQUFNO0FBQUEsZ0JBQzFDLEVBQUUsUUFBUSxFQUFFO0FBQUEsZ0JBQ1osQ0FBQyxHQUFHLE1BQU0sR0FBR0EsU0FBUSxrQkFBa0IsQ0FBQyxPQUFPQSxTQUFRLGtCQUFrQixDQUFDO0FBQUEsY0FDNUUsRUFBRSxLQUFLLElBQUksQ0FBQztBQUFBLHNDQUNjLE1BQU07QUFDOUIsb0JBQUksZ0JBQWdCLEdBQUc7QUFDckIseUJBQU8sR0FBRyxXQUFXLElBQUksTUFBTTtBQUFBLG9CQUM3QixFQUFFLFFBQVEsRUFBRTtBQUFBLG9CQUNaLENBQUMsR0FBRyxNQUFNLHVCQUF1QixDQUFDLE9BQU8sYUFBYSxhQUFhLENBQUMsS0FBSyxZQUFZLFlBQVksQ0FBQztBQUFBLGtCQUNwRyxFQUFFLEtBQUssSUFBSSxDQUFDO0FBQUEsZ0JBQ2QsT0FBTztBQUNMLHlCQUFPLHlCQUF5QixXQUFXLElBQUksTUFBTSxDQUFDLEVBQ25ELEtBQUssR0FBRyxhQUFhLGFBQWEsQ0FBQyxLQUFLLFlBQVksRUFBRSxFQUN0RCxLQUFLLEdBQUcsQ0FBQyxhQUFhLENBQUM7QUFBQSxnQkFDNUI7QUFBQSxjQUNGLEdBQUcsQ0FBQztBQUFBLDRDQUM0QixZQUFZLE1BQU0sS0FBSyxNQUFNLElBQUksVUFBVSxDQUFDLElBQUksYUFBYSxJQUFJLElBQUksSUFBSSxVQUFVLE1BQU0sRUFBRSxPQUFPLE1BQU07QUFBQSxnQkFDdEksRUFBRSxRQUFRLElBQUksWUFBWTtBQUFBLGdCQUMxQixDQUFDLEdBQUcsTUFDRixHQUNFLGdCQUFnQixJQUNaLFVBQVUsQ0FBQyw0QkFBNEIsQ0FBQyxNQUN4QyxjQUFjLENBQUMsMkJBQTJCLENBQUMsSUFDakQ7QUFBQSxjQUNKLEVBQUUsS0FBSyxLQUFLLENBQUM7QUFBQTtBQUFBLFlBRW5CO0FBQ0EsbUJBQU87QUFBQSxVQUNUO0FBQ0EsZ0JBQU0sMkJBQTJCLE1BQWM7QUFDN0MsZ0JBQUksVUFBVTtBQUFBLG9DQUNnQixVQUFVO0FBQUEsY0FFaEMsYUFDSTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHlDQVFBO0FBQUE7QUFBQSwrQkFFYUEsU0FBUSxJQUFJLENBQUcsSUFDbEM7QUFBQTtBQUVOLHFCQUFTLElBQUksR0FBRyxJQUFJLGFBQWEsY0FBYyxLQUFLO0FBQ2xELHlCQUFXO0FBQUEsdUJBQ0ksQ0FBQyxNQUFNLE9BQU8sWUFBWSxtQ0FBbUMsQ0FBQztBQUFBLGNBRXZFLGFBQ0k7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGdDQUtjLFdBQVcsWUFBWSx1QkFBdUIsQ0FBQztBQUFBLDRCQUNuRCxDQUFDLE1BQU1BLFNBQVEsZ0NBQ3pCLEVBQ047QUFBQTtBQUFBLFlBRU47QUFDQSxtQkFBTztBQUFBLFVBQ1Q7QUFDQSxnQkFBTSxlQUFlLE1BQWM7QUFDakMsZ0JBQUksVUFBVSxxQkFBcUIsVUFBVTtBQUM3QyxxQkFBUyxJQUFJLEdBQUcsSUFBSSxhQUFhLGNBQWMsS0FBSztBQUNsRCx5QkFBVztBQUFBLG1CQUNBLENBQUMsV0FBVyxFQUFFLGFBQWEsR0FBRyxFQUFFLEtBQUssT0FBTywwQkFBMEIsQ0FBQztBQUFBO0FBQUEsWUFFcEY7QUFDQSx1QkFBVztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsc0NBS3FCLFdBQVc7QUFBQSx3Q0FDVCxXQUFXO0FBQzdDLG1CQUFPO0FBQUEsVUFDVDtBQUNBLGlCQUFPO0FBQUEsaURBQ3NDLE9BQU8sS0FBSyxLQUFLLEtBQUssZUFBZSxhQUFhO0FBQUEsVUFDekYsYUFBYSxpQkFBaUIsR0FBRyxnQkFBZ0IsTUFBTSxDQUFDO0FBQUEsVUFDeEQsYUFBYSxVQUFVLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQUEsaUNBQ3RCLE9BQU8sZ0JBQWdCLGlCQUFpQixhQUFhLE9BQU8sWUFBWSxFQUFFLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEseUVBTW5DLGFBQWE7QUFBQTtBQUFBLDZDQUV6QyxXQUFXLFlBQVksV0FBVztBQUFBLGNBQ2pFLHlCQUF5QixDQUFDO0FBQUEsNkNBQ0ssZUFBZSxhQUFhLFdBQVc7QUFBQSxnQkFDcEUsYUFBYSxDQUFDO0FBQUEseUNBQ1csV0FBVztBQUFBLGtCQUNsQyxlQUFlLENBQUM7QUFBQSxpQ0FDRCxJQUFJLFdBQVc7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsNkJBTW5CLFlBQVk7QUFBQSxnQ0FDVCxPQUFPLEtBQUssS0FBSyxNQUFNLE9BQU8sS0FBSyxLQUFLO0FBQUE7QUFBQSx3Q0FFaEMsYUFBYTtBQUFBO0FBQUEsMkNBRVYsWUFBWTtBQUFBO0FBQUEsY0FFekMsT0FBTyxhQUFhLEdBQUcsT0FBTyxLQUFLLE9BQU8sa0NBQWtDLGNBQWMsQ0FBQztBQUFBO0FBQUE7QUFBQSxRQUd2RztBQUNBLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWE7QUFBQSxZQUNYLE1BQU0sR0FBRyxXQUFXLFNBQVMsSUFBSSxXQUFXLElBQUksSUFBSSxXQUFXLElBQUksV0FBVyxJQUFJLFVBQVUsSUFBSSxZQUFZLElBQUksYUFBYTtBQUFBLFlBQzdILG1CQUFtQixNQUFNLE9BQU8sTUFBTSxFQUFFLEtBQUssTUFBTTtBQUFBLFVBQ3JEO0FBQUEsVUFDQSxZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsU0FBUyxDQUFDO0FBQUEsWUFDekMsZUFBZSxFQUFFLEdBQUcsYUFBYTtBQUFBLFlBQ2pDO0FBQUEsVUFDRjtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUdPLE1BQU0sMENBQTBDLENBQ3JELFFBQ0EsZUFDZ0I7QUFDaEIsY0FBTSxhQUFhLE9BQU8sQ0FBQyxFQUFFO0FBQzdCLGNBQU0sUUFBUSxXQUFXO0FBQ3pCLGNBQU0sWUFBWSxXQUFXLFFBQVEsQ0FBQztBQUN0QyxjQUFNLFdBQVcsV0FBVztBQUM1QixjQUFNLFlBQVksV0FBVztBQUM3QixjQUFNLFlBQVksV0FBVyxNQUFNLEdBQUcsUUFBUSxDQUFDO0FBQy9DLGNBQU0sWUFBWSxVQUFVLEtBQUssU0FBUztBQUMxQyxjQUFNLFdBQVcsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDO0FBQ2pDLGNBQU0sa0JBQWtCLFdBQVc7QUFDbkMsY0FBTSxXQUFXLE9BQU8sQ0FBQyxFQUFFO0FBQzNCLGNBQU0sY0FBYyxpQkFBaUIsV0FBVyxDQUFDO0FBQ2pELGNBQU0sY0FBYyxpQkFBaUIsZUFBZTtBQUNwRCxjQUFNLGNBQWMsVUFBVSxPQUFPLENBQUMsV0FBVyxTQUFTLENBQUM7QUFFM0QsY0FBTSxnQkFBZ0I7QUFDdEIsY0FBTSxhQUFhLFlBQVksTUFBTSxJQUFJLElBQUksWUFBWSxNQUFNLElBQUksSUFBSTtBQUN2RSxjQUFNLGFBQWEsZ0JBQWdCO0FBQ25DLGNBQU0sV0FBVyxhQUFhLGNBQWM7QUFDNUMsY0FBTSxpQkFBaUIsV0FBVztBQUNsQyxjQUFNLGdCQUFnQixXQUFXLFdBQVc7QUFDNUMsY0FBTSxlQUFlLFVBQVUsS0FBSyxXQUFXLElBQUk7QUFFbkQsY0FBTSxrQkFBb0MsQ0FBQztBQUMzQyxjQUFNLGlCQUFpQixDQUFDLFdBQVcsV0FBVyxXQUFXLFdBQVc7QUFDcEUsY0FBTSxTQUFTLFVBQVUsYUFBYSxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTTtBQUM1RCxlQUFPLE9BQU8sSUFBSSxHQUFHLGtCQUFrQixXQUFXO0FBQ2xELHdCQUFnQixLQUFLLEdBQUcsMkJBQTJCLGNBQWMsQ0FBQztBQUNsRSx3QkFBZ0IsS0FBSyxHQUFHLDJCQUEyQixNQUFNLENBQUM7QUFDMUQsd0JBQWdCLEtBQUssR0FBRywyQkFBMkIsT0FBTyxDQUFDLEVBQUUsSUFBSSxDQUFDO0FBQ2xFLFlBQUksT0FBTyxXQUFXLEdBQUc7QUFDdkIsMEJBQWdCLEtBQUssR0FBRywyQkFBMkIsVUFBVSxhQUFhLE9BQU8sQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQUEsUUFDNUY7QUFDQSxjQUFNLGtCQUFrQixDQUFDLFdBQVcsV0FBVyxTQUFTO0FBQ3hELHdCQUFnQixLQUFLLEdBQUcsMkJBQTJCLGVBQWUsQ0FBQztBQUVuRSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxnQkFBTSxZQUFZLGVBQWU7QUFDakMsZ0JBQU0sSUFBSSxjQUFjLEtBQUssT0FBTyxDQUFDLEVBQUUsVUFBVSxXQUFXLFdBQVc7QUFDdkUsZ0JBQU0sSUFBSSxjQUFjLHNCQUFzQixPQUFPLFFBQVEsV0FBVztBQUN4RSxnQkFBTSxTQUFTLGNBQWMsVUFBVSxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLEtBQUssTUFBTTtBQUNoRixnQkFBTSxpQkFBaUIsQ0FBQyxHQUFHLEdBQUcsTUFBTTtBQUNwQyxnQkFBTSxhQUNKLE9BQU8sV0FBVyxJQUFJLGNBQWMsZ0NBQWdDLE9BQU8sQ0FBQyxFQUFFLEtBQUssTUFBTSxJQUFJO0FBQy9GLGNBQUksWUFBWTtBQUNkLDJCQUFlLEtBQUssVUFBVTtBQUFBLFVBQ2hDO0FBQ0EsZ0JBQU0sYUFBYSxnQkFBZ0I7QUFDbkMsZ0JBQU0sU0FBUyxlQUFlLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxVQUFVO0FBQ3RFLGdCQUFNQSxZQUFXLDRCQUE0QixPQUFPLENBQUMsRUFBRSxRQUFRO0FBQy9ELGdCQUFNLFFBQVEsTUFBTTtBQUNsQixvQkFBUSxhQUFhO0FBQUEsY0FDbkIsS0FBSztBQUNILHVCQUFPO0FBQUEsK0JBQ2NBLFNBQVE7QUFBQSwrQkFDUkEsU0FBUTtBQUFBLGNBQy9CLEtBQUs7QUFDSCx1QkFBTztBQUFBLCtCQUNjQSxTQUFRO0FBQUEsK0JBQ1JBLFNBQVE7QUFBQSxjQUMvQixLQUFLO0FBQ0gsdUJBQU87QUFBQTtBQUFBO0FBQUEsY0FHVDtBQUNFLHNCQUFNLElBQUksTUFBTSxHQUFHLFdBQVcsOEJBQThCO0FBQUEsWUFDaEU7QUFBQSxVQUNGO0FBRUEsaUJBQU87QUFBQSxzQ0FDMkIsRUFBRSxLQUFLLEtBQUssS0FBSyxjQUFjO0FBQUEsb0RBQ2pCLE9BQU8sS0FBSyxLQUFLLEtBQUssVUFBVSxNQUFNLFVBQVU7QUFBQSxVQUMxRixhQUFhLGlCQUFpQixHQUFHLGdCQUFnQixNQUFNLENBQUM7QUFBQSxVQUN4RCxhQUFhLFVBQVUsQ0FBQyxZQUFZLFlBQVksQ0FBQyxDQUFDLENBQUM7QUFBQSxpQ0FDNUIsT0FBTyxnQkFBZ0IscUJBQXFCLFVBQVUsRUFBRSxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxzREFLcEMsYUFBYTtBQUFBO0FBQUE7QUFBQTtBQUFBLHVDQUk1QixjQUFjO0FBQUE7QUFBQSx3REFFRyxjQUFjLGlCQUFpQixhQUFhO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxvQ0FLaEUsRUFBRSxhQUFhLEdBQUcsRUFBRSxLQUFLLE9BQU8scUJBQXFCLENBQUM7QUFBQTtBQUFBLG9DQUV0RCxFQUFFLEtBQUssS0FBSztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGlDQU9mLGFBQWE7QUFBQSxjQUVoQyxhQUNJO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsb0NBT2tCLFdBQVcsWUFBWSx1QkFBdUIsQ0FBQztBQUFBLCtCQUNwREEsU0FBUSxnQ0FDckI7QUFBQTtBQUFBLCtCQUVhQSxTQUFRLElBQUksQ0FBRyxJQUNsQztBQUFBLDBCQUNjLE9BQU8sWUFBWSxrQ0FBa0MsQ0FBQztBQUFBLDJCQUNyRCxFQUFFLGFBQWEsR0FBRyxFQUFFLEtBQUssT0FBTyxtQkFBbUIsQ0FBQztBQUFBLDZDQUNsQyxXQUFXLFlBQVksV0FBVztBQUFBLHVDQUN4QyxXQUFXO0FBQUEsZ0JBQ2xDLE1BQU0sQ0FBQztBQUFBLDhCQUNPLGdCQUFnQixJQUFJLFdBQVcsV0FBVztBQUFBO0FBQUE7QUFBQSxnREFHeEJBLFNBQVEsS0FBSyxNQUFNO0FBQUEsWUFDbkQsRUFBRSxRQUFRLEVBQUU7QUFBQSxZQUNaLENBQUMsR0FBRyxNQUFNLEdBQUdBLFNBQVEsa0JBQWtCLENBQUMsT0FBT0EsU0FBUSxrQkFBa0IsQ0FBQztBQUFBLFVBQzVFLEVBQUUsS0FBSyxJQUFJLENBQUM7QUFBQSx3RUFDOENBLFNBQVEsS0FBSyxNQUFNLENBQUMsRUFBRSxLQUFLLFlBQVksRUFBRSxLQUFLLEdBQUcsQ0FBQztBQUFBLHlEQUNqRSxNQUFNO0FBQUEsWUFDL0MsRUFBRSxRQUFRLEVBQUU7QUFBQSxZQUNaLENBQUMsR0FBRyxNQUFNLEdBQUcsYUFBYSxDQUFDLDBCQUEwQixDQUFDLElBQUk7QUFBQSxVQUM1RCxFQUFFLEtBQUssS0FBSyxDQUFDO0FBQUEsK0JBQ0ksSUFBSSxXQUFXO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSw0QkFLbEIsVUFBVTtBQUFBLGdDQUNOLE9BQU8sS0FBSyxLQUFLLE1BQU0sT0FBTyxLQUFLLEtBQUs7QUFBQSxtQ0FDckMsVUFBVTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsZ0JBSzdCLE9BQU8sYUFBYSxHQUFHLE9BQU8sS0FBSyxPQUFPLGlDQUFpQyxjQUFjLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQSxRQUl4RztBQUNBLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWE7QUFBQSxZQUNYLE1BQU0sR0FBRyxXQUFXLFNBQVMsSUFBSSxXQUFXLElBQUksV0FBVyxJQUFJLFVBQVUsSUFBSSxVQUFVO0FBQUEsWUFDdkYsbUJBQW1CLE1BQU0sT0FBTyxNQUFNLEVBQUUsS0FBSyxNQUFNO0FBQUEsVUFDckQ7QUFBQSxVQUNBLFlBQVksT0FBTztBQUFBLFlBQ2pCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sYUFBYSxTQUFTLENBQUM7QUFBQSxZQUN6QyxlQUFlLEVBQUUsR0FBRyxhQUFhO0FBQUEsWUFDakM7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxjQUFjLENBQUMsU0FBeUIsZUFBNEM7QUFDL0YsUUFBQUQsaUJBQWUsUUFBUSxRQUFRLFVBQVU7QUFDekMsWUFDRSxXQUFXLGNBQWMsTUFDekIsUUFBUSxZQUFZLFNBQVMsT0FBTyxLQUNwQyxRQUFRLFlBQVksZUFBZSxVQUFVLEdBQzdDO0FBQ0Esa0JBQVEsUUFBUSx3Q0FBd0MsUUFBUSxRQUFRLFVBQVUsQ0FBQztBQUFBLFFBQ3JGLE9BQU87QUFDTCxrQkFBUSxRQUFRLDZCQUE2QixRQUFRLFFBQVEsVUFBVSxDQUFDO0FBQUEsUUFDMUU7QUFBQSxNQUNGO0FBRU8sTUFBTSw2QkFBNkIsQ0FBQyxlQUN6Qyw0QkFBNEIsVUFBc0U7QUFBQTtBQUFBOzs7QUNsY3BHLE1BMEJNRSxrQkFtQkEsZ0JBMEJBLGVBMkJBLFlBdUJBLFlBdUJBLGVBZUEsc0JBdURBLCtCQStCTztBQXJQYjtBQUFBO0FBQUE7QUFHQTtBQUVBO0FBR0E7QUFrQkEsTUFBTUEsbUJBQWlCLENBQUMsV0FBd0M7QUFDOUQsWUFBSSxDQUFDLFVBQVUsT0FBTyxTQUFTLEdBQUc7QUFDaEMsZ0JBQU0sSUFBSSxNQUFNLGdCQUFnQjtBQUFBLFFBQ2xDO0FBQ0EsWUFBSSxPQUFPLENBQUMsRUFBRSw4QkFBK0IsT0FBTyxDQUFDLEVBQUUsK0JBQStCO0FBQ3BGLGdCQUFNLElBQUksTUFBTSxzQ0FBc0M7QUFBQSxRQUN4RDtBQUVBLFlBQUksT0FBTyxVQUFVLEdBQUc7QUFDdEIsY0FBSSxZQUFZLE9BQU8sQ0FBQyxFQUFFLEtBQUssU0FBUyxNQUFNLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQztBQUM5RCxjQUFJLE9BQU8sV0FBVyxHQUFHO0FBQ3ZCLHdCQUFZLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDO0FBQUEsVUFDeEQ7QUFDQSxjQUFJLENBQUMsV0FBVztBQUNkLGtCQUFNLElBQUksTUFBTSw2RUFBNkU7QUFBQSxVQUMvRjtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRUEsTUFBTSxpQkFBaUIsQ0FBQyxRQUF1QixXQUFtQixlQUErQjtBQUMvRixZQUFJLFFBQVE7QUFDWixpQkFBUyxJQUFJLFlBQVksR0FBRyxLQUFLLEdBQUcsRUFBRSxHQUFHO0FBQ3ZDLG1CQUFTO0FBQUEsc0JBQ1MsT0FBTyxXQUFXLFdBQVcsQ0FBQyxDQUFDLE9BQU8sYUFBYSxpQkFBaUIsR0FBRyxVQUFVLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQSwyQkFJN0UsYUFBYSxvQkFBb0IsR0FBRyxTQUFTLENBQUM7QUFBQTtBQUFBO0FBQUEsZ0NBR3pDLGFBQWEsc0JBQXNCLEdBQUcsU0FBUyxDQUFDO0FBQUE7QUFBQSxRQUU5RTtBQUVBLGVBQU87QUFBQSxvQkFDVyxPQUFPLEtBQUssS0FBSztBQUFBO0FBQUE7QUFBQTtBQUFBLGNBSXZCLEtBQUs7QUFBQTtBQUFBO0FBQUE7QUFBQSxNQUluQjtBQUVBLE1BQU0sZ0JBQWdCLENBQUMsUUFBdUIsV0FBbUIsZUFBK0I7QUFDOUYsWUFBSSxRQUFRO0FBQ1osaUJBQVMsSUFBSSxZQUFZLEdBQUcsS0FBSyxHQUFHLEVBQUUsR0FBRztBQUN2QyxtQkFBUztBQUFBLDBCQUNhLE9BQU8sV0FBVyxXQUFXLENBQUMsQ0FBQyxPQUFPLGFBQWEsaUJBQWlCLEdBQUcsVUFBVSxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSx5Q0FLbkUsYUFBYSxvQkFBb0IsR0FBRyxTQUFTLENBQUM7QUFBQTtBQUFBLGdDQUV2RCxhQUFhLG9CQUFvQixHQUFHLFNBQVMsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBLG9DQUkxQyxhQUFhLHNCQUFzQixHQUFHLFNBQVMsQ0FBQztBQUFBO0FBQUEsUUFFbEY7QUFFQSxlQUFPO0FBQUE7QUFBQTtBQUFBLGdCQUdPLEtBQUs7QUFBQTtBQUFBO0FBQUEsTUFHckI7QUFFQSxNQUFNLGFBQWEsQ0FBQyxRQUF1QixXQUFtQixlQUErQjtBQUMzRixZQUFJLFFBQVE7QUFDWixpQkFBUyxJQUFJLFlBQVksR0FBRyxLQUFLLEdBQUcsRUFBRSxHQUFHO0FBQ3ZDLG1CQUFTO0FBQUEsMEJBQ2EsT0FBTyxXQUFXLFdBQVcsQ0FBQyxDQUFDLE9BQU8sYUFBYSxpQkFBaUIsR0FBRyxVQUFVLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQSwrQkFJN0UsYUFBYSxvQkFBb0IsR0FBRyxTQUFTLENBQUM7QUFBQSw0QkFDakQsYUFBYSxvQkFBb0IsR0FBRyxTQUFTLENBQUM7QUFBQTtBQUFBLG9DQUV0QyxhQUFhLHNCQUFzQixHQUFHLFNBQVMsQ0FBQztBQUFBO0FBQUEsUUFFbEY7QUFFQSxlQUFPO0FBQUE7QUFBQTtBQUFBLGdCQUdPLEtBQUs7QUFBQTtBQUFBO0FBQUEsTUFHckI7QUFFQSxNQUFNLGFBQWEsQ0FBQyxRQUF1QixXQUFtQixlQUErQjtBQUMzRixZQUFJLFFBQVE7QUFDWixpQkFBUyxJQUFJLFlBQVksR0FBRyxLQUFLLEdBQUcsRUFBRSxHQUFHO0FBQ3ZDLG1CQUFTO0FBQUEsMEJBQ2EsT0FBTyxXQUFXLFdBQVcsQ0FBQyxDQUFDLE9BQU8sYUFBYSxpQkFBaUIsR0FBRyxVQUFVLENBQUM7QUFBQTtBQUFBLDZCQUUvRSxhQUFhLG9CQUFvQixHQUFHLFNBQVMsQ0FBQztBQUFBO0FBQUEsK0JBRTVDLGFBQWEsb0JBQW9CLEdBQUcsU0FBUyxDQUFDO0FBQUEsNkJBQ2hELGFBQWEsb0JBQW9CLEdBQUcsU0FBUyxDQUFDO0FBQUE7QUFBQSxvQ0FFdkMsYUFBYSxzQkFBc0IsR0FBRyxTQUFTLENBQUM7QUFBQTtBQUFBLFFBRWxGO0FBRUEsZUFBTztBQUFBO0FBQUE7QUFBQSxnQkFHTyxLQUFLO0FBQUE7QUFBQTtBQUFBLE1BR3JCO0FBRUEsTUFBTSxnQkFBZ0IsQ0FBQyxRQUF1QixXQUFtQixlQUFzQztBQUNyRyxnQkFBUSxXQUFXLE1BQU07QUFBQSxVQUN2QixLQUFLO0FBQ0gsbUJBQU8sZUFBZSxRQUFRLFdBQVcsV0FBVyxLQUFLLE1BQU07QUFBQSxVQUNqRSxLQUFLO0FBQ0gsbUJBQU8sY0FBYyxRQUFRLFdBQVcsV0FBVyxLQUFLLE1BQU07QUFBQSxVQUNoRSxLQUFLO0FBQ0gsbUJBQU8sV0FBVyxRQUFRLFdBQVcsV0FBVyxLQUFLLE1BQU07QUFBQSxVQUM3RCxLQUFLO0FBQ0gsbUJBQU8sV0FBVyxRQUFRLFdBQVcsV0FBVyxLQUFLLE1BQU07QUFBQSxVQUM3RDtBQUNFLGtCQUFNLElBQUksTUFBTSxjQUFjO0FBQUEsUUFDbEM7QUFBQSxNQUNGO0FBRUEsTUFBTSx1QkFBdUIsQ0FBQyxRQUErQixlQUEyQztBQUN0RyxjQUFNLGNBQWMsVUFBVSxTQUFTLE9BQU8sQ0FBQyxFQUFFLEtBQUssTUFBTSxHQUFHLFdBQVcsSUFBSTtBQUM5RSxjQUFNLFlBQVksT0FBTyxDQUFDLEVBQUU7QUFDNUIsY0FBTSxhQUFhLFVBQVUsS0FBSyxXQUFXO0FBQzdDLGNBQU0sa0JBQW9DO0FBQUEsVUFDeEMsRUFBRSx1QkFBdUIsTUFBTSxXQUFXO0FBQUEsVUFDMUMsRUFBRSxxQkFBc0IsTUFBTSxXQUFXLEtBQUs7QUFBQSxRQUNoRDtBQUVBLGNBQU0sbUJBQW1CLE9BQU8sVUFBVSxLQUFLLE9BQU8sQ0FBQyxFQUFFO0FBQ3pELFlBQUksV0FBVyxTQUFTLEdBQUc7QUFDekIsMEJBQWdCLEtBQUssRUFBRSxNQUFNLG1CQUFtQixPQUFPLENBQUMsRUFBRSwwQkFBMkIsTUFBTSxXQUFXLE1BQU0sQ0FBQztBQUFBLFFBQy9HO0FBRUEsd0JBQWdCLEtBQUssR0FBRywyQkFBMkIsT0FBTyxDQUFDLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDL0UsY0FBTSxvQkFBd0QsQ0FBQyxNQUFNO0FBRXJFLGNBQU0sa0JBQWtCLENBQUMsaUJBQStCO0FBQ3RELGdCQUFNLFNBQVMsZUFBZSxVQUFVLE9BQU8sQ0FBQyxFQUFFLFVBQVUsWUFBWSxNQUFNO0FBQzlFLGdCQUFNLFFBQVEsY0FBYyxLQUFLLE9BQU8sQ0FBQyxFQUFFLFVBQVUsVUFBVSxNQUFNO0FBQ3JFLGdCQUFNLFdBQVcsTUFBTSxLQUFLO0FBQzVCLGdCQUFNLGFBQWEsY0FBYyxRQUFRLFVBQVUsUUFBUSxVQUFVO0FBQ3JFLGdCQUFNLFdBQThCO0FBQUEsWUFDbEMsRUFBRSxNQUFNLGVBQWUsTUFBTSxNQUFNO0FBQUEsWUFDbkMsRUFBRSxNQUFNLFFBQVEsTUFBTSxPQUFPLFFBQVEsV0FBVyxLQUFLLE9BQU87QUFBQSxVQUM5RDtBQUNBLGNBQUksV0FBVyxTQUFTLEdBQUc7QUFDekIscUJBQVMsS0FBSyxFQUFFLE1BQU0sa0JBQWtCLE1BQU8sbUJBQW1CLFdBQVcsTUFBaUMsQ0FBQztBQUFBLFVBQ2pIO0FBRUEsaUJBQU87QUFBQSxjQUNHLGFBQWEsaUJBQWlCLFFBQVEsRUFBRSxpQkFBaUIsT0FBTyxNQUFNLENBQUM7QUFBQSxjQUN2RSxhQUFhLFVBQVUsQ0FBQztBQUFBLGNBQ3hCLGFBQWEsc0NBQXNDLHNCQUFzQixDQUFDO0FBQUE7QUFBQSw0QkFFNUQsT0FBTyxnQkFBZ0IsWUFBWSxDQUFDO0FBQUE7QUFBQSwwQkFFdEMsUUFBUTtBQUFBLGNBQ3BCLFVBQVU7QUFBQTtBQUFBO0FBQUEsUUFHdEI7QUFFQSxlQUFPO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixhQUFhLEVBQUUsTUFBTSxHQUFHLFdBQVcsSUFBSSxHQUFHLGdCQUFnQixJQUFJLGtCQUFrQjtBQUFBLFVBQ2hGLFlBQVksT0FBTztBQUFBLFlBQ2pCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sYUFBYSxVQUFVLE9BQU8sQ0FBQyxFQUFFLFNBQVMsQ0FBQztBQUFBLFlBQzdELGVBQWUsRUFBRSxHQUFHLEtBQUs7QUFBQSxjQUFLLFVBQVUsS0FBSyxXQUFXLElBQUk7QUFBQTtBQUFBLFlBQXVCLEVBQUU7QUFBQSxZQUNyRjtBQUFBLFVBQ0Y7QUFBQSxVQUNBO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFQSxNQUFNLGdDQUFnQyxDQUFDLFFBQStCLGVBQTZDO0FBQ2pILFlBQUksT0FBTyxTQUFTLEdBQUc7QUFDckIsZ0JBQU0sZUFBZSxPQUFPLENBQUMsRUFBRSxpQkFBaUI7QUFDaEQsZ0JBQU0sUUFDSixPQUFPLFVBQVUsS0FBSyxPQUFPLENBQUMsRUFBRSxPQUM1QixPQUFPLENBQUMsRUFBRSxnQ0FDUixPQUFPLENBQUMsRUFBRSxlQUFlLEVBQUUsQ0FBQyxJQUM1QixPQUFPLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLElBQy9CO0FBRU4sZ0JBQU0sWUFBWSxPQUFPLENBQUMsRUFBRSxLQUFLO0FBQ2pDLGdCQUFNLGFBQWEsSUFBSSxXQUFXLElBQUksU0FBUyxFQUFFLEtBQUssQ0FBQztBQUN2RCxjQUFJLE9BQU8sVUFBVSxHQUFHO0FBQ3RCLGtCQUFNLE9BQU8sT0FBTyxDQUFDLEVBQUUsaUJBQWlCO0FBQ3hDLHFCQUFTLElBQUksR0FBRyxJQUFJLEtBQUssUUFBUSxLQUFLO0FBQ3BDLHlCQUFXLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLE9BQU8sYUFBYSxDQUFDLENBQUM7QUFDcEQseUJBQVcsT0FBTyxLQUFLLENBQUMsQ0FBQyxJQUFJLFNBQVMsSUFBSSxPQUFPLGFBQWEsSUFBSSxLQUFLLE1BQU0sQ0FBQztBQUFBLFlBQ2hGO0FBQUEsVUFDRixPQUFPO0FBQ0wseUJBQWEsUUFBUSxDQUFDLEdBQUcsTUFBTyxXQUFXLE9BQU8sQ0FBQyxDQUFDLElBQUksT0FBTyxDQUFDLENBQUU7QUFBQSxVQUNwRTtBQUVBLGdCQUFNLE9BQWlCLENBQUM7QUFDeEIscUJBQVcsUUFBUSxDQUFDLE1BQU0sS0FBSyxLQUFLLENBQUMsQ0FBQztBQUV0QyxpQkFBTyxFQUFFLE1BQU0sV0FBVyxNQUFNLE9BQU8sS0FBSztBQUFBLFFBQzlDLE9BQU87QUFDTCxpQkFBTztBQUFBLFFBQ1Q7QUFBQSxNQUNGO0FBRU8sTUFBTSxNQUFNLENBQUMsU0FBeUIsZUFBb0M7QUFDL0UsUUFBQUEsaUJBQWUsUUFBUSxNQUFNO0FBQzdCLGNBQU0sb0JBQW9CLDhCQUE4QixRQUFRLFFBQVEsVUFBVTtBQUNsRixnQkFBUSxRQUFRLHFCQUFxQixRQUFRLFFBQVEsaUJBQWlCLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFBQSxNQUMxRjtBQUFBO0FBQUE7OztBQ3pQQSxNQTJCTUMsa0JBTUEseUNBc0NBLHNCQTZFQSxxQkFtS0EsK0JBR0EsMENBR0Esc0NBR0EsMkJBYUEsOEJBd0RPLDRCQVlBLGFBS1Asc0JBV08sa0NBS0EsbUJBVVAsMEJBbURPLFNBS0Esd0JBZ0JBLDhCQUtBO0FBN2ZiO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFFQTtBQUlBO0FBZ0JBLE1BQU1BLG1CQUFpQixDQUFDLFdBQXdDO0FBQzlELFlBQUlDLEtBQUksT0FBTyx5QkFBeUIsQ0FBQyxVQUFVLE9BQU8sV0FBVyxJQUFJO0FBQ3ZFLGdCQUFNLElBQUksTUFBTSw0QkFBNEI7QUFBQSxRQUM5QztBQUFBLE1BQ0Y7QUFFQSxNQUFNLDBDQUEwQyxDQUM5QyxPQUNBLFlBQ0EscUJBQzhCO0FBQzlCLGNBQU0saUJBQWlCLFdBQVcsV0FBVztBQUM3QyxjQUFNLDJCQUEyQixNQUFNLEtBQUssTUFBTTtBQUNsRCxZQUFJLGdCQUFnQjtBQUNsQixtQ0FBeUIsT0FBTyxHQUFHLEdBQUcseUJBQXlCLElBQUksQ0FBRTtBQUFBLFFBQ3ZFO0FBQ0EsY0FBTSxlQUFlLE9BQU8sZUFBZSxLQUFLLFlBQVksV0FBVztBQUN2RSxjQUFNLGNBQWMsV0FBVyxZQUFZLE1BQU07QUFDakQsY0FBTSxVQUFVLFdBQVcsUUFBUSxNQUFNO0FBQ3pDLGNBQU0sWUFBc0IsZUFBZ0IsV0FBaUMsVUFBVSxNQUFNLElBQUksQ0FBQztBQUNsRyxjQUFNLE9BQU8sV0FBVyxLQUFLLE1BQU07QUFDbkMscUJBQWEscUJBQXFCLGtCQUFrQiwwQkFBMEIsYUFBYSxTQUFTLFdBQVcsSUFBSTtBQUVuSCxjQUFNLDRCQUE0QixhQUFhO0FBQUEsVUFDN0M7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0EsV0FBVztBQUFBLFFBQ2I7QUFFQSxjQUFNLGdCQUFnQixPQUFPLE9BQU8sQ0FBQyxHQUFHLFVBQVU7QUFDbEQsWUFBSSxjQUFjO0FBQ2hCLGlCQUFPLE9BQU8sZUFBZSxFQUFFLGFBQWEsU0FBUyxNQUFNLFdBQVcsVUFBVSxXQUFXLFNBQVMsQ0FBQztBQUFBLFFBQ3ZHLE9BQU87QUFDTCxpQkFBTyxPQUFPLGVBQWUsRUFBRSxhQUFhLFNBQVMsTUFBTSxVQUFVLFdBQVcsU0FBUyxDQUFDO0FBQUEsUUFDNUY7QUFDQSxjQUFNLDJCQUEyQiwwQkFBMEIsTUFBTTtBQUNqRSxpQ0FBeUIsS0FBSyx5QkFBeUIsT0FBTyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDdEUsZUFBTyxDQUFDLGVBQWUsaUJBQWlCLDJCQUEyQix5QkFBeUI7QUFBQSxNQUM5RjtBQUVBLE1BQU0sdUJBQXVCLENBQzNCLGFBQ0EsZUFDcUU7QUFDckUsY0FBTSxpQkFBaUIsV0FBVyxXQUFXO0FBQzdDLGNBQU0sYUFBYSxVQUFVLEtBQUssV0FBVztBQUM3QyxjQUFNLGFBQWEsVUFBVSxLQUFLLFdBQVcsV0FBVztBQUN4RCxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFFBQzVDO0FBQ0EsY0FBTSxXQUE4QjtBQUFBLFVBQ2xDLEVBQUUsTUFBTSxjQUFjLE1BQU0sTUFBTTtBQUFBLFVBQ2xDLEVBQUUsTUFBTSxjQUFjLE1BQU0sTUFBTTtBQUFBLFFBQ3BDO0FBQ0EsWUFBSSxXQUFXLFlBQVksVUFBVSxHQUFHO0FBQ3RDLGdCQUFNLEtBQUssV0FBVyxZQUFZLFdBQVcsWUFBWSxTQUFTLENBQUM7QUFDbkUsZ0JBQU0sS0FBSyxXQUFXLFFBQVEsV0FBVyxRQUFRLFNBQVMsQ0FBQztBQUMzRCxnQkFBTSxVQUFVLFdBQVcsS0FBSyxXQUFXLEtBQUssU0FBUyxJQUFJLENBQUM7QUFDOUQsZ0JBQU0sUUFBUSxXQUFXLEtBQUssV0FBVyxLQUFLLFNBQVMsQ0FBQztBQUN4RCxnQkFBTSxvQkFBb0IsQ0FBQyxFQUFFLFVBQVU7QUFDdkMsMEJBQWdCO0FBQUEsWUFDZCxFQUFFLHVCQUF1QixNQUFNLEdBQUc7QUFBQSxZQUNsQyxFQUFFLHVCQUF1QixNQUFNLEdBQUc7QUFBQSxZQUNsQyxFQUFFLHVCQUF1QixNQUFNLFFBQVE7QUFBQSxZQUN2QyxFQUFFLHVCQUF1QixNQUFNLE1BQU07QUFBQSxVQUN2QztBQUNBLG1CQUFTO0FBQUEsWUFDUCxFQUFFLE1BQU0sTUFBTSxNQUFNLE1BQU07QUFBQSxZQUMxQixFQUFFLE1BQU0sTUFBTSxNQUFNLE1BQU07QUFBQSxZQUMxQixFQUFFLE1BQU0sV0FBVyxNQUFNLE1BQU07QUFBQSxZQUMvQixFQUFFLE1BQU0sU0FBUyxNQUFNLE1BQU07QUFBQSxVQUMvQjtBQUVBLGNBQUksb0JBQW9CO0FBQ3hCLGNBQUksV0FBVyxZQUFZLFdBQVcsR0FBRztBQUN2QyxrQkFBTSxLQUFLLFdBQVcsWUFBWSxXQUFXLFlBQVksU0FBUyxDQUFDO0FBQ25FLGtCQUFNLEtBQUssV0FBVyxRQUFRLFdBQVcsUUFBUSxTQUFTLENBQUM7QUFDM0Qsa0JBQU0sVUFBVSxXQUFXLEtBQUssV0FBVyxLQUFLLFNBQVMsSUFBSSxDQUFDO0FBQzlELGtCQUFNLFFBQVEsV0FBVyxLQUFLLFdBQVcsS0FBSyxTQUFTLENBQUM7QUFDeEQsZ0NBQW9CLENBQUMsRUFBRSxVQUFVO0FBQ2pDLDRCQUFnQjtBQUFBLGNBQ2QsRUFBRSx1QkFBdUIsTUFBTSxHQUFHO0FBQUEsY0FDbEMsRUFBRSx1QkFBdUIsTUFBTSxHQUFHO0FBQUEsY0FDbEMsRUFBRSx1QkFBdUIsTUFBTSxRQUFRO0FBQUEsY0FDdkMsRUFBRSx1QkFBdUIsTUFBTSxNQUFNO0FBQUEsWUFDdkM7QUFFQSxxQkFBUztBQUFBLGNBQ1AsRUFBRSxNQUFNLE1BQU0sTUFBTSxNQUFNO0FBQUEsY0FDMUIsRUFBRSxNQUFNLE1BQU0sTUFBTSxNQUFNO0FBQUEsY0FDMUIsRUFBRSxNQUFNLFdBQVcsTUFBTSxNQUFNO0FBQUEsY0FDL0IsRUFBRSxNQUFNLFNBQVMsTUFBTSxNQUFNO0FBQUEsWUFDL0I7QUFBQSxVQUNGO0FBQ0EsaUJBQU8sQ0FBQyxpQkFBaUIsVUFBVSxNQUFNLG1CQUFtQixpQkFBaUI7QUFBQSxRQUMvRSxPQUFPO0FBQ0wsY0FBSSxnQkFBZ0I7QUFDbEIsa0JBQU0sSUFBSSxNQUFNLHVFQUF1RTtBQUFBLFVBQ3pGO0FBQ0EsZ0JBQU0sZ0JBQWdCLFVBQVUsZUFBZSxXQUFXLFdBQVc7QUFDckUsMEJBQWdCO0FBQUEsWUFDZCxFQUFFLHVCQUF1QixNQUFNLGNBQWM7QUFBQSxZQUM3QyxFQUFFLHVCQUF1QixNQUFNLFdBQVcsS0FBSztBQUFBLFlBQy9DLEVBQUUsdUJBQXVCLE1BQU0sV0FBVyxRQUFRO0FBQUEsVUFDcEQ7QUFDQSxtQkFBUztBQUFBLFlBQ1AsRUFBRSxNQUFNLGlCQUFpQixNQUFNLE9BQU8sUUFBUSxjQUFjLE9BQU87QUFBQSxZQUNuRSxFQUFFLE1BQU0sUUFBUSxNQUFNLE9BQU8sUUFBUSxXQUFXLEtBQUssT0FBTztBQUFBLFlBQzVELEVBQUUsTUFBTSxXQUFXLE1BQU0sT0FBTyxRQUFRLFdBQVcsUUFBUSxPQUFPO0FBQUEsVUFDcEU7QUFFQSxnQkFBTSxVQUFVLFdBQVcsS0FBSyxPQUFPLENBQUMsS0FBSyxRQUFRLE1BQU0sR0FBRztBQUM5RCxpQkFBTyxDQUFDLGlCQUFpQixVQUFVLENBQUMsQ0FBQyxTQUFTLE9BQU8sS0FBSztBQUFBLFFBQzVEO0FBQUEsTUFDRjtBQUVBLE1BQU0sc0JBQXNCLENBQzFCLGNBQ0EsR0FDQSxNQUNBLGlCQUNBLFlBQ0EsS0FDQSxLQUNBLE9BQ0EsVUFDQSxTQUNBLG1CQUNBLHNCQUNXO0FBQ1gsY0FBTSxpQkFBaUIsV0FBVyxXQUFXO0FBQzdDLGNBQU0sV0FBVyxFQUFFLEtBQUs7QUFDeEIsY0FBTSxTQUFTLGVBQWUsVUFBVSxFQUFFLEtBQUssUUFBUSxlQUFlO0FBRXRFLFlBQUksV0FBVyxZQUFZLFVBQVUsR0FBRztBQUN0QyxjQUFJLFFBQVE7QUFDWixjQUFJLFFBQVE7QUFDWixjQUFJLFdBQVc7QUFDZixnQkFBTSxVQUFVLFFBQVEsaUJBQWlCLElBQUk7QUFDN0MsY0FBSSxtQkFBbUI7QUFDckIsb0JBQVE7QUFBQTtBQUFBLDZCQUVlLE9BQU8sZUFBZSxPQUFPO0FBQUEsaUNBQ3pCLE9BQU8scUJBQXFCLE9BQU87QUFBQSw0Q0FDeEIsT0FBTztBQUFBO0FBQUE7QUFBQTtBQUFBLGtDQUlqQixFQUFFLGdCQUFnQixVQUFVLENBQUM7QUFBQSxvQkFDM0MsR0FBRztBQUFBO0FBQUEsVUFFbkIsT0FBTztBQUNMLG9CQUFRO0FBQUE7QUFBQSw2QkFFZSxPQUFPLGVBQWUsT0FBTztBQUFBLGtDQUN4QixFQUFFLGdCQUFnQixVQUFVLENBQUM7QUFBQSxvQkFDM0MsR0FBRztBQUFBO0FBQUEsVUFFbkI7QUFFQSxjQUFJLFdBQVcsWUFBWSxXQUFXLEdBQUc7QUFDdkMsa0JBQU0sVUFBVSxRQUFRLGlCQUFpQixJQUFJO0FBQzdDLGdCQUFJLG1CQUFtQjtBQUNyQixzQkFBUTtBQUFBO0FBQUEsNkJBRWEsT0FBTyxlQUFlLE9BQU87QUFBQSxpQ0FDekIsT0FBTyxxQkFBcUIsT0FBTyx5QkFBeUIsT0FBTztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsWUFLOUYsT0FBTztBQUNMLHNCQUFRO0FBQUE7QUFBQSw2QkFFYSxPQUFPLGVBQWUsT0FBTztBQUFBO0FBQUEsWUFFcEQ7QUFDQSx1QkFBVztBQUFBO0FBQUE7QUFBQSxVQUdiO0FBRUEsZ0JBQU0sY0FBYztBQUFBLGNBQ1YsYUFBYSxpQkFBaUIsUUFBUSxFQUFFLGlCQUFpQixHQUFHLE1BQU0sQ0FBQztBQUFBO0FBQUEsY0FFbkUsYUFBYSxVQUFVLENBQUM7QUFBQSxnQkFDdEIsYUFBYSxzQ0FBc0MscUJBQXFCLENBQUM7QUFBQTtBQUFBLDhCQUUzRCxPQUFPLGdCQUFnQixZQUFZLENBQUM7QUFBQSwrQkFDbkMsT0FBTyxnQkFBZ0IsWUFBWSxDQUFDO0FBQUE7QUFBQSw0QkFFdkMsUUFBUSxJQUFJLEtBQUs7QUFBQTtBQUFBLGdCQUU3QixLQUFLO0FBQUEsZ0JBQ0wsS0FBSztBQUFBLGdCQUNMLFFBQVE7QUFBQSxnQkFDUixHQUFHO0FBQUE7QUFBQTtBQUFBO0FBSWYsaUJBQU87QUFBQSxRQUNULE9BQU87QUFDTCxjQUFJLGdCQUFnQjtBQUNsQixrQkFBTSxJQUFJLE1BQU0sdUVBQXVFO0FBQUEsVUFDekY7QUFDQSxnQkFBTSxjQUFjLFdBQVcsWUFBWTtBQUMzQyxnQkFBTSxXQUFXLFdBQVcsS0FBSztBQUNqQyxjQUFJLFVBQVU7QUFDZCxjQUFJLFNBQVM7QUFDWCxzQkFBVTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsZ0NBUWdCLEVBQUUsZ0JBQWdCLFVBQVUsQ0FBQztBQUFBLGtCQUMzQyxHQUFHO0FBQUE7QUFBQSxVQUVqQixPQUFPO0FBQ0wsc0JBQVU7QUFBQTtBQUFBLDhCQUVjLEVBQUUsZ0JBQWdCLFVBQVUsQ0FBQztBQUFBLGdCQUMzQyxHQUFHO0FBQUE7QUFBQSxVQUVmO0FBQ0EsZ0JBQU0sY0FBYztBQUFBLGNBQ1YsYUFBYSxpQkFBaUIsUUFBUSxFQUFFLGlCQUFpQixHQUFHLE1BQU0sQ0FBQztBQUFBO0FBQUEsY0FFbkUsYUFBYSxVQUFVLENBQUM7QUFBQSxnQkFDdEIsYUFBYSxzQ0FBc0MscUJBQXFCLENBQUM7QUFBQSw4QkFDM0QsT0FBTyxnQkFBZ0IsWUFBWSxDQUFDO0FBQUEsK0JBQ25DLE9BQU8sZ0JBQWdCLFlBQVksQ0FBQztBQUFBO0FBQUEsd0NBRTNCLFdBQVc7QUFBQTtBQUFBLDRCQUV2QixRQUFRLElBQUksS0FBSztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSx1Q0FNTixjQUFjLENBQUM7QUFBQSwwQ0FDWixhQUFhLDBCQUEwQixLQUFLLFdBQVcsQ0FBQztBQUFBLDJDQUN2RCxhQUFhLDBCQUEwQixLQUFLLFdBQVcsQ0FBQztBQUFBO0FBQUEsMEJBRXpFLGNBQWMsQ0FBQztBQUFBO0FBQUE7QUFBQSwrQkFHVixPQUFPLFdBQVcsVUFBVSxJQUFJO0FBQUEsK0NBQ2hCO0FBQUEsWUFDM0I7QUFBQSxZQUNBLE9BQU8sT0FBTyxXQUFXO0FBQUEsWUFDekI7QUFBQSxVQUNGLENBQUM7QUFBQSxvQ0FDaUIsT0FBTyxXQUFXLFFBQVEsYUFBYSxpQkFBaUIsVUFBVSxRQUFRLENBQUM7QUFBQSxvQkFDM0YsT0FBTztBQUFBO0FBQUEsZ0JBRVgsR0FBRztBQUFBO0FBQUE7QUFBQTtBQUlmLGlCQUFPO0FBQUEsUUFDVDtBQUFBLE1BQ0Y7QUFjQSxNQUFNLGdDQUFnQyxDQUFDLGVBQ3JDLEdBQUcsV0FBVyxNQUFNLElBQUksV0FBVyxRQUFRLElBQUksV0FBVyxPQUFPLElBQUksV0FBVyxZQUFZLE1BQU07QUFFcEcsTUFBTSwyQ0FBMkMsQ0FBQyxlQUNoRCxHQUFHLDhCQUE4QixVQUFVLENBQUMsSUFBSSxXQUFXLGVBQWU7QUFFNUUsTUFBTSx1Q0FBdUMsQ0FBQyxlQUM1QyxHQUFHLDhCQUE4QixVQUFVLENBQUMsSUFBSSxXQUFXLFlBQVksSUFBSSxXQUFXLFNBQVM7QUFFakcsTUFBTSw0QkFBNEIsQ0FBQyxnQkFBK0Q7QUFBQSxRQUNoRyxRQUFRLFdBQVc7QUFBQSxRQUNuQixTQUFTLENBQUMsVUFBVSxTQUFTLGNBQWMsWUFBWSxFQUFFLFdBQVcsUUFBa0I7QUFBQSxRQUN0RixVQUFVLFdBQVc7QUFBQSxRQUNyQixhQUFhLFdBQVc7QUFBQSxRQUN4QixTQUFTLFdBQVc7QUFBQSxRQUNwQixNQUFNLFdBQVc7QUFBQSxNQUNuQjtBQU1BLE1BQU0sK0JBQStCLENBQ25DLE1BQ0EsT0FDQSxrQkFDQSxlQUNnQjtBQUNoQixjQUFNLENBQUMsb0JBQW9CLFdBQVcsSUFBSTtBQUFBLFVBQ3hDO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQ0EsY0FBTSxJQUFJLGNBQWMsS0FBSyxNQUFNLFVBQVUsTUFBTSxLQUFLLE1BQU07QUFDOUQsY0FBTSxXQUFXLEVBQUUsS0FBSztBQUV4QixjQUFNLE1BQU07QUFDWixZQUFJLE1BQU07QUFDVixZQUFJLG1CQUFtQixpQkFBaUI7QUFDdEMsaUJBQU8sWUFBWSxRQUFRO0FBQUEsUUFDN0IsT0FBTztBQUNMLGlCQUFPLFlBQVksUUFBUTtBQUFBLFFBQzdCO0FBQ0EsY0FBTSxDQUFDLGlCQUFpQixVQUFVLFNBQVMsbUJBQW1CLGlCQUFpQixJQUFJO0FBQUEsVUFDakY7QUFBQSxVQUNBO0FBQUEsUUFDRjtBQUNBLHdCQUFnQixLQUFLLEdBQUcsMkJBQTJCLE1BQU0sTUFBTSxXQUFXLENBQUM7QUFDM0UsY0FBTSxvQkFBd0QsQ0FBQyxNQUFNO0FBQ3JFLGVBQU87QUFBQSxVQUNMO0FBQUEsVUFDQSxhQUFhO0FBQUEsWUFDWCxNQUFNLEdBQUcsV0FBVyxRQUFRLElBQUksT0FBTyxJQUFJLGlCQUFpQixJQUFJLGlCQUFpQjtBQUFBLFlBQ2pGO0FBQUEsVUFDRjtBQUFBLFVBQ0EsWUFBWSxPQUFPO0FBQUEsWUFDakIsU0FBUyxDQUFDLEVBQUUsTUFBTSxhQUFhLFVBQVUsTUFBTSxTQUFTLENBQUM7QUFBQSxZQUN6RCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxVQUFVLEtBQUssV0FBVyxJQUFJO0FBQUE7QUFBQSxZQUF1QixFQUFFO0FBQUEsWUFDckY7QUFBQSxVQUNGO0FBQUEsVUFDQSxpQkFBaUIsQ0FBQyxpQkFDaEI7QUFBQSxZQUNFO0FBQUEsWUFDQTtBQUFBLFlBQ0EsTUFBTSxLQUFLO0FBQUEsWUFDWCxZQUFZO0FBQUEsWUFDWjtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxVQUNGO0FBQUEsUUFDSjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLDZCQUE2QixDQUFDLGVBQStEO0FBQ3hHLGNBQU0sa0JBQW1CLFdBQVcsc0JBQWlDLElBQUksUUFBUTtBQUVqRixjQUFNLE9BQU8sMEJBQTBCLFVBQVU7QUFFakQsWUFBSSxLQUFLLGFBQWEsR0FBRztBQUN2QixnQkFBTSxJQUFJLE1BQU0sd0VBQXdFO0FBQUEsUUFDMUY7QUFDQSxjQUFNLHdCQUF3QixFQUFFLGlCQUFpQixHQUFHLE1BQU0sVUFBVSxHQUFHO0FBQ3ZFLGVBQU8sRUFBRSxHQUFHLHVCQUF1QixVQUFVLHlDQUF5QyxxQkFBcUIsRUFBRTtBQUFBLE1BQy9HO0FBRU8sTUFBTSxjQUFjLENBQUMsU0FBeUIsZUFBNEM7QUFDL0YsUUFBQUQsaUJBQWUsUUFBUSxNQUFNO0FBQzdCLGdCQUFRLFFBQVEsNkJBQTZCLGVBQWUsUUFBUSxPQUFPLENBQUMsR0FBRyxPQUFPLFVBQVUsQ0FBQztBQUFBLE1BQ25HO0FBRUEsTUFBTSx1QkFBdUI7QUFBQSxRQUMzQixTQUFTO0FBQUEsUUFDVCxVQUFVO0FBQUEsUUFDVixpQkFBaUI7QUFBQSxRQUNqQixhQUFhLENBQUM7QUFBQSxRQUNkLFNBQVMsQ0FBQztBQUFBLFFBQ1YsTUFBTSxDQUFDO0FBQUEsUUFDUCxjQUFjO0FBQUEsUUFDZCxXQUFXLENBQUM7QUFBQSxNQUNkO0FBRU8sTUFBTSxtQ0FBbUMsQ0FBQyxlQUErRDtBQUM5RyxjQUFNLFNBQVMsV0FBVztBQUMxQixlQUFPLEVBQUUsUUFBUSxHQUFHLHNCQUFzQixVQUFVLE9BQU87QUFBQSxNQUM3RDtBQUVPLE1BQU0sb0JBQW9CLENBQUMsU0FBeUIsZUFBNEM7QUFDckcsUUFBQUEsaUJBQWUsUUFBUSxNQUFNO0FBQzdCLGdCQUFRLFFBQVEsNkJBQTZCLHFCQUFxQixRQUFRLE9BQU8sQ0FBQyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQUEsTUFDeEc7QUFPQSxNQUFNLDJCQUEyQixDQUMvQixNQUNBLE9BQ0Esa0JBQ0EsZUFDZ0I7QUFDaEIsY0FBTSxDQUFDLG9CQUFvQixXQUFXLElBQUk7QUFBQSxVQUN4QztBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsUUFDRjtBQUNBLGNBQU0sTUFBTTtBQUFBO0FBQUE7QUFHWixjQUFNLE1BQU07QUFDWixjQUFNLElBQUksY0FBYyxLQUFLLE1BQU0sVUFBVSxNQUFNLEtBQUssTUFBTTtBQUM5RCxjQUFNLG9CQUF3RCxDQUFDLE1BQU07QUFDckUsY0FBTSxDQUFDLGlCQUFpQixVQUFVLFNBQVMsbUJBQW1CLGlCQUFpQixJQUFJO0FBQUEsVUFDakY7QUFBQSxVQUNBO0FBQUEsUUFDRjtBQUNBLHdCQUFnQixLQUFLLEdBQUcsMkJBQTJCLE1BQU0sTUFBTSxXQUFXLENBQUM7QUFDM0UsZUFBTztBQUFBLFVBQ0w7QUFBQSxVQUNBLGFBQWE7QUFBQSxZQUNYLE1BQU0sR0FBRyxXQUFXLFFBQVEsSUFBSSxPQUFPLElBQUksaUJBQWlCLElBQUksaUJBQWlCO0FBQUEsWUFDakY7QUFBQSxVQUNGO0FBQUEsVUFDQSxZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxNQUFNLFNBQVMsQ0FBQztBQUFBLFlBQ3pELGVBQWUsRUFBRSxHQUFHLEtBQUs7QUFBQSxjQUFLLFVBQVUsS0FBSyxXQUFXLElBQUk7QUFBQTtBQUFBLFlBQXVCLEVBQUU7QUFBQSxZQUNyRjtBQUFBLFVBQ0Y7QUFBQSxVQUNBLGlCQUFpQixDQUFDLGlCQUNoQjtBQUFBLFlBQ0U7QUFBQSxZQUNBO0FBQUEsWUFDQSxNQUFNLEtBQUs7QUFBQSxZQUNYLFlBQVk7QUFBQSxZQUNaO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBLE1BQU0sZ0NBQWdDLFNBQVM7QUFBQSxZQUMvQztBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFVBQ0Y7QUFBQSxRQUNKO0FBQUEsTUFDRjtBQUVPLE1BQU0sVUFBVSxDQUFDLFNBQXlCLGVBQXdDO0FBQ3ZGLFFBQUFBLGlCQUFlLFFBQVEsTUFBTTtBQUM3QixnQkFBUSxRQUFRLHlCQUF5QixXQUFXLFFBQVEsT0FBTyxDQUFDLEdBQUcsT0FBTyxVQUFVLENBQUM7QUFBQSxNQUMzRjtBQUVPLE1BQU0seUJBQXlCLENBQUMsZUFBMkQ7QUFDaEcsY0FBTSxlQUFlLFdBQVc7QUFDaEMsY0FBTSxZQUFZLFdBQVc7QUFFN0IsY0FBTSxPQUFPLDBCQUEwQixVQUFVO0FBRWpELFlBQUksaUJBQWlCLEdBQUc7QUFDdEIsZ0JBQU0sSUFBSSxNQUFNLDZEQUE2RDtBQUFBLFFBQy9FO0FBQ0EsWUFBSSxLQUFLLGFBQWEsR0FBRztBQUN2QixnQkFBTSxJQUFJLE1BQU0sb0VBQW9FO0FBQUEsUUFDdEY7QUFDQSxjQUFNLG9CQUFvQixFQUFFLGNBQWMsV0FBVyxHQUFHLE1BQU0sVUFBVSxHQUFHO0FBQzNFLGVBQU8sRUFBRSxHQUFHLG1CQUFtQixVQUFVLHFDQUFxQyxpQkFBaUIsRUFBRTtBQUFBLE1BQ25HO0FBRU8sTUFBTSwrQkFBK0IsQ0FBQyxlQUEyRDtBQUN0RyxjQUFNLFNBQVMsV0FBVztBQUMxQixlQUFPLEVBQUUsUUFBUSxHQUFHLHNCQUFzQixVQUFVLE9BQU87QUFBQSxNQUM3RDtBQUVPLE1BQU0sZ0JBQWdCLENBQUMsU0FBeUIsZUFBd0M7QUFDN0YsUUFBQUEsaUJBQWUsUUFBUSxNQUFNO0FBQzdCLGdCQUFRLFFBQVEseUJBQXlCLGlCQUFpQixRQUFRLE9BQU8sQ0FBQyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQUEsTUFDaEc7QUFBQTtBQUFBOzs7QUNoZ0JBLE1BdUJNRSxrQkFxREEsbUNBMEpPLGtCQUtBO0FBM09iO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFDQTtBQUdBO0FBY0EsTUFBTUEsbUJBQWlCLENBQUMsUUFBK0IsZUFBZ0Q7QUFDckcsWUFBSSxPQUFPLFNBQVMsS0FBSyxPQUFPLFNBQVMsR0FBRztBQUMxQyxnQkFBTSxJQUFJLE1BQU0sMENBQTBDO0FBQUEsUUFDNUQ7QUFDQSxZQUFJLE9BQU8sV0FBVyxLQUFLLE9BQU8sQ0FBQyxFQUFFLFNBQVMsT0FBTyxDQUFDLEVBQUUsTUFBTTtBQUM1RCxnQkFBTSxJQUFJLE1BQU0sb0RBQW9EO0FBQUEsUUFDdEU7QUFDQSxZQUFJLE9BQU8sV0FBVyxLQUFLLE9BQU8sQ0FBQyxFQUFFLGFBQWEsT0FBTyxDQUFDLEVBQUUsVUFBVTtBQUNwRSxnQkFBTSxJQUFJLE1BQU0sa0RBQWtEO0FBQUEsUUFDcEU7QUFDQSxZQUFJLE9BQU8sQ0FBQyxFQUFFLDhCQUErQixPQUFPLFNBQVMsR0FBRztBQUM5RCxnQkFBTSxJQUFJLE1BQU0sMkRBQTJEO0FBQUEsUUFDN0U7QUFDQSxZQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssV0FBVyxLQUFLLE9BQU8sQ0FBQyxFQUFFLEtBQUssV0FBVyxLQUFLLE9BQU8sQ0FBQyxFQUFFLEtBQUssV0FBVyxPQUFPLENBQUMsRUFBRSxLQUFLLFFBQVE7QUFDakgsZ0JBQU0sSUFBSSxNQUFNLHVGQUF1RjtBQUFBLFFBQ3pHO0FBRUEsWUFBSSxPQUFPLFNBQVMsR0FBRztBQUVyQixjQUFJLE9BQU8sQ0FBQyxFQUFFLGFBQWEsT0FBTyxDQUFDLEVBQUUsVUFBVTtBQUM3QyxrQkFBTSxJQUFJLE1BQU0sa0RBQWtEO0FBQUEsVUFDcEU7QUFFQSxjQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssV0FBVyxPQUFPLENBQUMsRUFBRSxLQUFLLFFBQVE7QUFDbkQsa0JBQU0sSUFBSSxNQUFNLHNEQUFzRDtBQUFBLFVBQ3hFO0FBQ0EsY0FBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLEdBQUcsTUFBTSxNQUFNLE9BQU8sQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLEdBQUcsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHO0FBQ3pGLGtCQUFNLElBQUksTUFBTSx1REFBdUQ7QUFBQSxVQUN6RTtBQUFBLFFBQ0Y7QUFFQSxZQUFJLFdBQVcsWUFBWSxHQUFHO0FBRTVCLGNBQUksT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLEtBQU0sT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLEtBQUssT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLE1BQU0sR0FBSTtBQUMzRixrQkFBTSxJQUFJLE1BQU0sb0RBQW9EO0FBQUEsVUFDdEU7QUFDQSxjQUNFLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxJQUFJLENBQUMsR0FBRyxNQUFNLE1BQU0sV0FBVyxRQUFRLE1BQU0sT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsR0FBRyxNQUFNLEtBQUssR0FBRyxJQUFJLEdBQzdHO0FBQ0Esa0JBQU0sSUFBSSxNQUFNLHdGQUF3RjtBQUFBLFVBQzFHO0FBRUEsY0FBSSxPQUFPLENBQUMsRUFBRSxLQUFLLFdBQVcsT0FBTyxDQUFDLEVBQUUsS0FBSyxRQUFRO0FBQ25ELGtCQUFNLElBQUksTUFBTSw2RUFBNkU7QUFBQSxVQUMvRjtBQUNBLGdCQUFNLEtBQUssT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLElBQUk7QUFDekMsZ0JBQU0sS0FBSyxPQUFPLENBQUMsRUFBRSxLQUFLLFdBQVcsSUFBSTtBQUN6QyxjQUFJLFdBQVcsWUFBWSxLQUFLLEtBQUssS0FBSyxFQUFFLEtBQUssV0FBVyxZQUFZLEtBQUssS0FBSyxNQUFNLEtBQUssS0FBSyxDQUFDLEdBQUc7QUFDcEcsa0JBQU0sSUFBSSxNQUFNLCtFQUErRTtBQUFBLFVBQ2pHO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFQSxNQUFNLG9DQUFvQyxDQUN4QyxRQUNBLGVBQ2dCO0FBQ2hCLGNBQU0sT0FBTyxVQUFVLGNBQWMsV0FBVyxNQUFNLE9BQU8sQ0FBQyxFQUFFLEtBQUssTUFBTTtBQUMzRSxjQUFNLFlBQVksT0FBTyxDQUFDLEVBQUU7QUFDNUIsY0FBTSxXQUFXO0FBQ2pCLGNBQU0sY0FBYyxPQUFPLENBQUMsRUFBRTtBQUM5QixjQUFNLFdBQVcsT0FBTyxDQUFDLEVBQUU7QUFDM0IsY0FBTSxhQUFhLFVBQVUsS0FBSyxXQUFXO0FBQzdDLGNBQU0sV0FBVyw4QkFBK0I7QUFDaEQsY0FBTSxhQUFhLFdBQVcsQ0FBQyxLQUFLLEtBQUssVUFBVSxLQUFLLE9BQU8sQ0FBQyxFQUFFLElBQUksSUFBSSxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsRUFBRTtBQUMxRixjQUFNLGFBQWEsT0FBTyxDQUFDLEVBQUU7QUFDN0IsY0FBTSxpQkFBaUIsT0FBTyxTQUFTLElBQUksT0FBTyxDQUFDLElBQUk7QUFDdkQsY0FBTSxpQkFBaUIsaUJBQ25CLFdBQ0UsQ0FBQyxLQUFLLEtBQUssVUFBVSxLQUFLLGVBQWUsSUFBSSxJQUFJLENBQUMsQ0FBQyxJQUNuRCxlQUFlLE9BQ2pCO0FBR0osY0FBTSx1QkFBdUIsV0FBVyxXQUFXLEtBQU0sV0FBVyxXQUFXLEtBQUssV0FBVyxDQUFDLE1BQU07QUFDdEcsY0FBTSxzQkFBc0IseUJBQXlCLFNBQVMsV0FBVyxXQUFXO0FBR3BGLGNBQU0sZ0JBQWdCLGlCQUFpQixVQUFVO0FBQ2pELGNBQU0sZ0JBQWdCLHlCQUF5QixDQUFDLFlBQVksa0JBQWtCO0FBQzlFLGNBQU0sYUFBYSxnQkFBZ0IsZ0JBQWdCO0FBQ25ELGNBQU0saUJBQWlCLGlCQUFpQixDQUFDLFdBQVcsZ0JBQWdCO0FBQ3BFLGNBQU0sUUFBUSxjQUFjLFNBQVMsNkJBQTZCLFdBQVcsV0FBVyxRQUFRLGNBQWM7QUFDOUcsY0FBTSxRQUFRLGNBQWMsU0FBUyxVQUFVLFdBQVcsTUFBTTtBQUNoRSxjQUFNLFlBQVksaUJBQ2QsY0FBYyxjQUFjLDZCQUE2QixXQUFXLGVBQWdCLE1BQU0sSUFDMUY7QUFDSixjQUFNLFNBQVMsZUFBZSxVQUFVLFVBQVUsWUFBWSxRQUFRLFVBQVU7QUFDaEYsY0FBTSxpQkFBaUIsQ0FBQyxPQUFPLEtBQUs7QUFDcEMsWUFBSSxXQUFXO0FBQ2IseUJBQWUsS0FBSyxTQUFTO0FBQUEsUUFDL0I7QUFDQSxjQUFNLGNBQWMsQ0FBQyxZQUFZLFVBQVU7QUFDM0MsWUFBSSxnQkFBZ0I7QUFDbEIsc0JBQVksS0FBSyxjQUFlO0FBQUEsUUFDbEM7QUFDQSxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sYUFBYSxXQUFXO0FBQUEsVUFDdkQsRUFBRSx1QkFBdUIsTUFBTSxLQUFLO0FBQUEsVUFDcEMsRUFBRSx1QkFBdUIsTUFBTSxXQUFXLFVBQVU7QUFBQSxVQUNwRCxHQUFHLDJCQUEyQixHQUFHLGFBQWEsV0FBVztBQUFBLFFBQzNEO0FBQ0EsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFDdEQsZ0JBQU0sV0FBOEI7QUFBQSxZQUNsQyxFQUFFLE1BQU0sZUFBZSxNQUFNLE1BQU07QUFBQSxZQUNuQyxFQUFFLE1BQU0sUUFBUSxNQUFNLE1BQU07QUFBQSxZQUM1QixFQUFFLE1BQU0sY0FBYyxNQUFNLE1BQU07QUFBQSxVQUNwQztBQUNBLGlCQUFPO0FBQUEsUUFDSCxhQUFhLGlCQUFpQixRQUFRLEVBQUUsaUJBQWlCLEdBQUcsZ0JBQWdCLE1BQU0sQ0FBQztBQUFBLFFBQ25GLGFBQWEsVUFBVSxDQUFDO0FBQUEsWUFDcEIsYUFBYSxzQ0FBc0Msc0JBQXNCLENBQUM7QUFBQSxpQ0FDckQsT0FBTyxnQkFBZ0IsWUFBWSxDQUFDO0FBQUE7QUFBQTtBQUFBLGFBR3hELE1BQU07QUFDUCxnQkFBSSxVQUFVO0FBQ1oscUJBQU87QUFBQSwwQkFDSyxNQUFNLFlBQVksZ0JBQWdCLENBQUM7QUFBQSwwQkFDbkMsV0FBVyxzQkFBc0IsbUJBQW1CO0FBQUEsNEJBQ2xELGVBQWUsSUFBSSwwQkFBMEIsT0FBTztBQUFBLFlBQ3BFLE9BQU87QUFDTCxxQkFBTyxpQkFBaUIsTUFBTSxZQUFZLFlBQVksQ0FBQztBQUFBLFlBQ3pEO0FBQUEsVUFDRixHQUFHLENBQUM7QUFBQTtBQUFBO0FBQUEsYUFHRCxNQUFNO0FBQ1AsZ0JBQUksc0JBQXNCO0FBRXhCLHFCQUFPLG9CQUFvQixNQUFNLFlBQVksR0FBRyxDQUFDO0FBQUEsWUFDbkQsV0FBVyxxQkFBcUI7QUFFOUIscUJBQU87QUFBQSxnQ0FDVyxPQUFPLFdBQVcsa0JBQWtCLGVBQWUsQ0FBQztBQUFBLCtCQUNyRCxNQUFNLFlBQVksYUFBYSxDQUFDO0FBQUEsWUFDbkQsT0FBTztBQUVMLHFCQUFPO0FBQUEsaUNBQ1ksTUFBTSxLQUFLLE9BQU87QUFBQSwwQkFDekIsTUFBTSxXQUFXLGlCQUFpQixlQUFlLENBQUM7QUFBQSxjQUM5RCxNQUFNLFdBQVcsaUJBQWlCLGlCQUFpQixPQUFPLENBQUM7QUFBQSwrQkFDMUMsTUFBTSxhQUFhLGVBQWUsQ0FBQztBQUFBLFlBQ3REO0FBQUEsVUFDRixHQUFHLENBQUM7QUFBQTtBQUFBO0FBQUEsYUFHRCxNQUFNO0FBQ1AsZ0JBQUksV0FBVztBQUNiLGtCQUFJLHNCQUFzQjtBQUV4QixvQkFBSSxVQUFVO0FBQ1oseUJBQU87QUFBQSx5Q0FDZ0IsVUFBVSxZQUFZLEdBQUcsQ0FBQztBQUFBLHdDQUMzQixXQUFXLGlDQUFpQyw4QkFBOEI7QUFBQTtBQUFBLGdCQUVsRyxPQUFPO0FBQ0wseUJBQU8sMEJBQTBCLFVBQVUsWUFBWSxHQUFHLENBQUM7QUFBQSxnQkFDN0Q7QUFBQSxjQUNGLFdBQVcscUJBQXFCO0FBRTlCLG9CQUFJLFVBQVU7QUFDWix5QkFBTztBQUFBLHlDQUNnQixPQUFPLFdBQVcsa0JBQWtCLGVBQWUsQ0FBQztBQUFBLHlDQUNwRCxVQUFVLFlBQVksc0JBQXNCLENBQUM7QUFBQSx3Q0FDOUMsV0FBVyxpQ0FBaUMsOEJBQThCO0FBQUE7QUFBQSxnQkFFbEcsT0FBTztBQUNMLHlCQUFPO0FBQUEseUNBQ2dCLE9BQU8sV0FBVyxrQkFBa0IsZUFBZSxDQUFDO0FBQUEseUNBQ3BELFVBQVUsWUFBWSxrQkFBa0IsQ0FBQztBQUFBLGdCQUNsRTtBQUFBLGNBQ0YsT0FBTztBQUVMLG9CQUFJLFVBQVU7QUFDWix5QkFBTztBQUFBLDBDQUNpQixNQUFNLGdCQUFnQixlQUFlLENBQUM7QUFBQSx5Q0FDdkMsVUFBVSxZQUFZLHVCQUF1QixDQUFDO0FBQUEsdUNBQ2hELFdBQVcsaUNBQWlDLDhCQUE4QjtBQUFBO0FBQUEsZ0JBRWpHLE9BQU87QUFDTCx5QkFBTywwQkFBMEIsVUFBVSxhQUFhLGVBQWUsQ0FBQztBQUFBLGdCQUMxRTtBQUFBLGNBQ0Y7QUFBQSxZQUNGLE9BQU87QUFDTCxxQkFBTywwQkFBMEIsV0FBWSxXQUFXLFFBQVEsUUFBUyxNQUFNLEtBQUssS0FBSztBQUFBLFlBQzNGO0FBQUEsVUFDRixHQUFHLENBQUM7QUFBQTtBQUFBLFFBRU4sT0FBTyxZQUFZLGNBQWMsR0FBRyxPQUFPLEtBQUssS0FBSyw0Q0FBNEMsQ0FBQztBQUFBO0FBQUEsUUFFeEc7QUFDQSxlQUFPO0FBQUEsVUFDTCxNQUFNO0FBQUEsVUFDTixhQUFhO0FBQUEsWUFDWCxNQUFNLFdBQVc7QUFBQSxZQUNqQixtQkFBbUIsWUFBWSxDQUFDLFFBQVEsUUFBUSxNQUFNLElBQUksQ0FBQyxRQUFRLE1BQU07QUFBQSxVQUMzRTtBQUFBLFVBQ0E7QUFBQSxVQUNBLFlBQVksT0FBTztBQUFBLFlBQ2pCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sYUFBYSxTQUFTLENBQUM7QUFBQSxZQUN6QyxlQUFlLEVBQUUsR0FBRyxLQUFLLEtBQUssYUFBYSxhQUFhLEVBQUUsR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFO0FBQUEsWUFDeEU7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLG1CQUFtQixDQUFDLFNBQXlCLGVBQWdEO0FBQ3hHLFFBQUFBLGlCQUFlLFFBQVEsUUFBUSxVQUFVO0FBQ3pDLGdCQUFRLFFBQVEsa0NBQWtDLFFBQVEsUUFBUSxVQUFVLENBQUM7QUFBQSxNQUMvRTtBQUVPLE1BQU0sa0NBQWtDLENBQUMsZUFDOUMsNEJBQTRCLEVBQUUsTUFBTSxXQUFXLE1BQWdCLFdBQVcsV0FBVyxVQUFvQixDQUFDO0FBQUE7QUFBQTs7O0FDNU81RyxNQWdCTSx1QkFVQSx3QkF1Q087QUFqRWI7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUdBO0FBUUEsTUFBTSx3QkFBd0IsQ0FBQyxPQUFlLE9BQWUsVUFBd0I7QUFDbkYsY0FBTSxpQkFBaUIsVUFBVTtBQUNqQyxjQUFNLDhCQUE4QixRQUFRLFNBQVMsUUFBUTtBQUM3RCxjQUFNLDhCQUE4QixRQUFRLFNBQVMsUUFBUTtBQUU3RCxZQUFJLGtCQUFrQiwrQkFBK0IsNkJBQTZCO0FBQ2hGLGdCQUFNLElBQUksTUFBTSwyQ0FBMkM7QUFBQSxRQUM3RDtBQUFBLE1BQ0Y7QUFFQSxNQUFNLHlCQUF5QixDQUFDLE9BQWUsT0FBZSxPQUFlLGFBQW9DO0FBQy9HLGNBQU0sY0FBYyxLQUFLLElBQUksS0FBSyxNQUFNLFFBQVEsU0FBUyxLQUFLLENBQUM7QUFDL0QsY0FBTSxjQUF3QixDQUFDLFdBQVc7QUFDMUMsY0FBTSxhQUFhO0FBQ25CLGNBQU0sa0JBQW9DO0FBQUEsVUFDeEMsRUFBRSx1QkFBdUIsTUFBTSxXQUFXO0FBQUEsVUFDMUMsRUFBRSxNQUFNLFVBQVUsTUFBTSxNQUFNO0FBQUEsVUFDOUIsRUFBRSxNQUFNLFVBQVUsTUFBTSxNQUFNO0FBQUEsVUFDOUIsR0FBRywyQkFBMkIsV0FBVztBQUFBLFFBQzNDO0FBRUEsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFDdEQsZ0JBQU0sU0FBUyxlQUFlLFVBQVUsVUFBVSxZQUFZLE1BQU07QUFDcEUsZ0JBQU0sV0FBVyxPQUFPLEtBQUs7QUFDN0IsZ0JBQU0sV0FBOEI7QUFBQSxZQUNsQyxFQUFFLE1BQU0sY0FBYyxNQUFNLE1BQU07QUFBQSxZQUNsQyxFQUFFLE1BQU0sU0FBUyxNQUFNLFNBQW1DO0FBQUEsWUFDMUQsRUFBRSxNQUFNLFNBQVMsTUFBTSxTQUFtQztBQUFBLFVBQzVEO0FBQ0EsaUJBQU87QUFBQSxVQUNELGFBQWEsaUJBQWlCLFFBQVEsRUFBRSxpQkFBaUIsTUFBTSxDQUFDO0FBQUEsVUFDaEUsYUFBYSxVQUFVLENBQUM7QUFBQSxVQUN4QixhQUFhLHNDQUFzQyxxQkFBcUIsQ0FBQztBQUFBLGdEQUNuQyxRQUFRO0FBQUE7QUFBQSxRQUV0RDtBQUVBLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWEsRUFBRSxNQUFNLEdBQUcsUUFBUSxHQUFHO0FBQUEsVUFDbkM7QUFBQSxVQUNBLFlBQVksT0FBTztBQUFBLFlBQ2pCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sYUFBYSxTQUFTLENBQUM7QUFBQSxZQUN6QyxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxhQUFhO0FBQUE7QUFBQSxZQUF1QixFQUFFO0FBQUEsWUFDcEU7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLFFBQVEsQ0FBQyxZQUFrQztBQUN0RCxZQUFJLFFBQVE7QUFDWixZQUFJLFFBQVE7QUFDWixZQUFJLFFBQVE7QUFDWixZQUFJLFFBQVEsT0FBTyxDQUFDLEVBQUUsNEJBQTZCO0FBQ2pELGtCQUFRLFFBQVEsT0FBTyxDQUFDLEVBQUUsY0FBYyxFQUFFLENBQUM7QUFDM0Msa0JBQVEsUUFBUSxPQUFPLENBQUMsRUFBRSxjQUFjLEVBQUUsQ0FBQztBQUMzQyxrQkFBUSxRQUFRLE9BQU8sQ0FBQyxFQUFFLGNBQWMsRUFBRSxDQUFDO0FBQUEsUUFDN0MsV0FBVyxRQUFRLE9BQU8sQ0FBQyxFQUFFLDRCQUE2QjtBQUN4RCxrQkFBUSxRQUFRLE9BQU8sQ0FBQyxFQUFFLGdCQUFnQixFQUFFLENBQUM7QUFDN0Msa0JBQVEsUUFBUSxPQUFPLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDO0FBQzdDLGtCQUFRLFFBQVEsT0FBTyxDQUFDLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQztBQUFBLFFBQy9DO0FBQ0EsWUFBSUMsS0FBSSxPQUFPLHNCQUFzQjtBQUNuQyxnQ0FBc0IsT0FBTyxPQUFPLEtBQUs7QUFBQSxRQUMzQztBQUVBLGdCQUFRLFFBQVEsdUJBQXVCLE9BQU8sT0FBTyxPQUFPLFFBQVEsT0FBTyxDQUFDLEVBQUUsUUFBUSxHQUFHLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQztBQUFBLE1BQ3pHO0FBQUE7QUFBQTs7O0FDbkZBLE1BdUJNLHdCQXlEQSx1QkF3QkEsdUJBTUEsNEJBNEZPLDBCQUdBO0FBN01iO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFDQTtBQUdBO0FBY0EsTUFBTSx5QkFBeUIsQ0FBQyxXQUFtQixLQUFhLEdBQVcsU0FBd0I7QUFDakcsWUFBSSxjQUFjLFVBQVUsU0FBUyxTQUFTLFNBQVMsU0FBUyxTQUFTLE9BQU87QUFDOUUsZ0JBQU0sSUFBSSxNQUFNLFNBQVMsSUFBSSxvQ0FBb0MsU0FBUyxHQUFHO0FBQUEsUUFDL0U7QUFFQSxjQUFNLGFBQWE7QUFBQTtBQUFBO0FBQUE7QUFJbkIsY0FBTSxXQUFXO0FBQUE7QUFBQSx5REFFc0MsR0FBRztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQVExRCxnQkFBUSxXQUFXO0FBQUEsVUFDakIsS0FBSztBQUNILG1CQUFPLEdBQUcsR0FBRyxJQUFJLENBQUM7QUFBQSxVQUNwQixLQUFLO0FBQ0gsZ0JBQUksU0FBUyxTQUFTLFNBQVMsT0FBTztBQUNwQyxxQkFBTyxjQUFjLEdBQUcsYUFBYSxJQUFJLEtBQUssQ0FBQztBQUFBLFlBQ2pELE9BQU87QUFHTCxxQkFBTztBQUFBLGdCQUNDLFVBQVUsV0FBVyxJQUFJLGtCQUFrQixDQUFDLElBQUksUUFBUTtBQUFBLFlBQ2xFO0FBQUEsVUFDRixLQUFLO0FBQ0gsZ0JBQUksU0FBUyxTQUFTLFNBQVMsT0FBTztBQUNwQyxxQkFBTyxjQUFjLEdBQUcsYUFBYSxJQUFJLEtBQUssQ0FBQztBQUFBLFlBQ2pELE9BQU87QUFHTCxxQkFBTztBQUFBLGtCQUNHLFVBQVUsZ0NBQWdDLENBQUMsS0FBSyxRQUFRO0FBQUEsWUFDcEU7QUFBQSxVQUNGLEtBQUs7QUFDSCxnQkFBSSxTQUFTLFNBQVMsU0FBUyxPQUFPO0FBQ3BDLHFCQUFPLGNBQWMsR0FBRyxhQUFhLElBQUksS0FBSyxDQUFDO0FBQUEsWUFDakQsT0FBTztBQUdMLHFCQUFPLEdBQUcsVUFBVSxlQUFlLElBQUksaUJBQWlCLENBQUMsS0FBSyxRQUFRO0FBQUEsWUFDeEU7QUFBQSxVQUNGLEtBQUs7QUFFSCxtQkFBTyxHQUFHLFVBQVUsWUFBWSxJQUFJLGtCQUFrQixDQUFDLEtBQUssUUFBUTtBQUFBLFVBRXRFO0FBQ0Usa0JBQU0sSUFBSSxNQUFNLGFBQWEsU0FBUyxvQkFBb0I7QUFBQSxRQUM5RDtBQUFBLE1BQ0Y7QUFFQSxNQUFNLHdCQUF3QixDQUFDLFVBQWtCLGFBQy9DLEdBQ0UsYUFBYSxJQUNUO0FBQUE7QUFBQSw4Q0FHQTtBQUFBLHNEQUM4QyxXQUFXLHNCQUFzQixHQUFHO0FBQUEsNENBQzlDLFdBQVcsc0JBQXNCLEdBQUcsb0NBQzlFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFlRixNQUFNLHdCQUF3QixDQUFDLFlBQWlDLGlCQUFnQyxhQUM5RjtBQUFBLDhEQUM0RCxXQUFXLGVBQWUsS0FBSztBQUFBLFVBQ25GLHVCQUF1QixXQUFXLFdBQVcsMkJBQTJCLFNBQVMsZUFBZSxDQUFDO0FBQUE7QUFHM0csTUFBTSw2QkFBNkIsQ0FBQyxRQUErQixlQUFpRDtBQUNsSCxjQUFNLGFBQWEsT0FBTyxDQUFDLEVBQUU7QUFDN0IsY0FBTSxlQUFlLE9BQU8sQ0FBQyxFQUFFO0FBQy9CLGNBQU0sY0FBYztBQUVwQixjQUFNLGFBQWE7QUFDbkIsY0FBTSxhQUFhLEtBQUssS0FBSyxVQUFVLEtBQUssWUFBWSxJQUFJLFVBQVU7QUFDdEUsY0FBTSxxQkFBcUIsYUFBYSxhQUFhLFNBQVMsQ0FBQztBQUMvRCxjQUFNLHFCQUFxQixVQUFVLGtCQUFrQixZQUFZLGtCQUFrQjtBQUNyRixjQUFNLHFCQUFxQixVQUFVLGtCQUFrQixjQUFjLENBQUMsSUFBSTtBQUUxRSxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sbUJBQW1CO0FBQUEsVUFDbEQsRUFBRSx1QkFBdUIsTUFBTSxtQkFBbUI7QUFBQSxVQUNsRCxHQUFHLDJCQUEyQixPQUFPLENBQUMsRUFBRSxNQUFNLE9BQU8sQ0FBQyxFQUFFLE1BQU0sV0FBVztBQUFBLFFBQzNFO0FBRUEsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFDdEQsZ0JBQU0sVUFBVSxjQUFjLFdBQVcsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU07QUFDbEYsZ0JBQU0sVUFBVSxjQUFjLFdBQVcsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLFFBQVEsVUFBVTtBQUM5RixnQkFBTSxTQUNKLFdBQVcsY0FBYyxVQUFVLFdBQVcsY0FBYyxLQUN4RCxxQkFBcUIsVUFBVSxPQUFPLENBQUMsRUFBRSxVQUFVLFlBQVksTUFBTSxJQUNyRSxlQUFlLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxZQUFZLFFBQVEsVUFBVTtBQUVqRixpQkFBTztBQUFBLFFBQ0gsYUFDQyxnQkFBZ0IsZUFBZSxLQUFLLEVBQ3BDLGdCQUFnQix3QkFBd0IsS0FBSyxFQUM3QyxnQkFBZ0Isd0JBQXdCLEtBQUssRUFDN0MsaUJBQWlCLFNBQVMsU0FBUyxNQUFNLENBQUM7QUFBQSxRQUMzQyxhQUFhLFVBQVUsQ0FBQztBQUFBLFVBQ3RCLGFBQWEsc0NBQXNDLHNCQUFzQixDQUFDO0FBQUE7QUFBQSxRQUU1RSxXQUFXLGNBQWMsTUFBTTtBQUFBLDBCQUNiLGtCQUFrQjtBQUFBLGdDQUNaLGtCQUFrQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFjMUMsV0FBVyxjQUFjLE1BQU07QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLCtCQUtSLGtCQUFrQjtBQUFBO0FBQUE7QUFBQTtBQUFBLFVBSXZDLHNCQUFzQixXQUFXLFFBQVEsS0FBSyxDQUFDO0FBQUE7QUFBQSxRQUVqRCxzQkFBc0IsWUFBWSxPQUFPLEtBQUssT0FBd0IsS0FBSyxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsTUFVOUUsc0JBQXNCLFdBQVcsUUFBUSxJQUFJLENBQUM7QUFBQTtBQUFBLElBRWhELHNCQUFzQixZQUFZLE9BQU8sS0FBSyxPQUF3QixJQUFJLENBQUM7QUFBQTtBQUFBLFFBRTdFO0FBQ0EsZUFBTztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sYUFBYTtBQUFBLFlBQ1gsTUFBTSxHQUFHLFdBQVcsUUFBUSxJQUFJLFdBQVcsU0FBUztBQUFBLFlBQ3BELG1CQUFtQixDQUFDLFFBQVEsTUFBTTtBQUFBLFVBQ3BDO0FBQUEsVUFDQSxZQUFZLE9BQU87QUFBQSxZQUNqQixTQUFTLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxPQUFPLENBQUMsRUFBRSxTQUFTLENBQUM7QUFBQSxZQUM3RCxlQUFlLEVBQUUsR0FBRyxLQUFLO0FBQUEsY0FBSyxhQUFhO0FBQUE7QUFBQSxZQUF1QixFQUFFO0FBQUEsWUFDcEU7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSwyQkFBMkIsQ0FBQyxlQUN2Qyw0QkFBNEIsRUFBRSxXQUFXLFdBQVcsVUFBb0IsQ0FBQztBQUVwRSxNQUFNLFlBQVksQ0FBQyxTQUF5QixlQUEwQztBQUMzRixnQkFBUSxRQUFRLDJCQUEyQixRQUFRLFFBQVEsVUFBVSxHQUFHO0FBQUEsVUFDdEUsUUFBUSxDQUFDLFFBQVEsT0FBTyxDQUFDLEdBQUcsUUFBUSxPQUFPLENBQUMsQ0FBQztBQUFBLFVBQzdDLFNBQVMsQ0FBQztBQUFBLFFBQ1osQ0FBQztBQUFBLE1BQ0g7QUFBQTtBQUFBOzs7QUNsTkEsTUE2Q00sZ0JBdUNBLGNBYUFDLGtCQThEQSx3QkFVQSw0Q0FvREEsNkJBbUNBLFdBYUEsaUJBMkJBLG1CQTJCQSwyQ0E0QkEsd0NBd0NBLG1CQVdBLDJCQWFBLHVCQTJEQSxzQkEwRkEsd0JBK0VBLHlCQW9KQSxxQ0FPTyxRQWtCQTtBQWh6QmI7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUNBO0FBR0E7QUFvQ0EsTUFBTSxpQkFBaUIsQ0FBQyxRQUFrQixlQUF1QztBQUMvRSxlQUFPO0FBQUEsVUFDTCxDQUFDLFVBQ0MsUUFBUSxNQUNQLE1BQU07QUFDTCxrQkFBTSxJQUFJLE1BQU0sb0RBQW9EO0FBQUEsVUFDdEU7QUFBQSxRQUNKO0FBRUEsWUFBSSxPQUFPLFNBQVMsR0FBRztBQUNyQixjQUFJLFdBQVcsU0FBUyxVQUFVO0FBQ2hDLGdCQUNFLEVBQ0UsT0FBTyxXQUFXLEtBQ2xCLE9BQU8sV0FBVyxLQUNqQixPQUFPLFdBQVcsS0FBSyxPQUFPLENBQUMsTUFBTSxLQUFLLE9BQU8sQ0FBQyxNQUFNLEtBQ3hELE9BQU8sV0FBVyxLQUFLLE9BQU8sQ0FBQyxNQUFNLEtBQUssT0FBTyxDQUFDLE1BQU0sS0FDeEQsT0FBTyxXQUFXLEtBQUssT0FBTyxDQUFDLE1BQU0sS0FBSyxPQUFPLENBQUMsTUFBTSxJQUUzRDtBQUNBLG9CQUFNLElBQUk7QUFBQSxnQkFDUjtBQUFBO0FBQUEsY0FFRjtBQUFBLFlBQ0Y7QUFBQSxVQUNGLFdBQVcsV0FBVyxTQUFTLFNBQVM7QUFDdEMsZ0JBQ0UsRUFDRSxPQUFPLFdBQVcsS0FDakIsT0FBTyxXQUFXLEtBQUssT0FBTyxDQUFDLE1BQU0sS0FBSyxPQUFPLENBQUMsTUFBTSxLQUN4RCxPQUFPLFdBQVcsS0FBSyxPQUFPLENBQUMsTUFBTSxLQUFLLE9BQU8sQ0FBQyxNQUFNLElBRTNEO0FBQ0Esb0JBQU0sSUFBSSxNQUFNLCtEQUErRDtBQUFBLFlBQ2pGO0FBQUEsVUFDRjtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRUEsTUFBTSxlQUFlLENBQUMsUUFBMkIsTUFBeUIsU0FBMkI7QUFDbkcsYUFBSztBQUFBLFVBQ0gsQ0FBQyxVQUNFLFNBQVMsS0FBSyxRQUFRLFNBQ3RCLE1BQU07QUFDTCxrQkFBTSxJQUFJLE1BQU0scUVBQXFFO0FBQUEsVUFDdkY7QUFBQSxRQUNKO0FBQ0EsY0FBTSxZQUFZLElBQUksTUFBTSxJQUFJLEVBQUUsS0FBSyxDQUFHO0FBQzFDLGFBQUssUUFBUSxDQUFDLE9BQU8sVUFBVyxVQUFVLEtBQUssSUFBSSxPQUFPLEtBQUssQ0FBRTtBQUNqRSxlQUFPO0FBQUEsTUFDVDtBQUVBLE1BQU1BLG1CQUFpQixDQUNyQixRQUNBLFlBQ0EsY0FDQSxRQUNBLE9BQ0EsUUFDUztBQUNULGNBQU0sQ0FBQyxlQUFlLGtCQUFrQixlQUFlLElBQ3JELGVBQWUsS0FBSyxDQUFDLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLE9BQU8sU0FBUyxJQUFJLElBQUksSUFBSSxFQUFFO0FBQ3JFLGNBQU0sT0FBTyxPQUFPLENBQUMsRUFBRSxLQUFLO0FBQzVCLFlBQUksZ0JBQWdCLEtBQUssT0FBTyxTQUFTLGlCQUFpQixPQUFPLGFBQWEsRUFBRSxLQUFLLFNBQVMsR0FBRztBQUMvRixpQkFBTyxhQUFhLEVBQUUsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLFVBQVUsSUFBSSxLQUFLLEtBQUssQ0FBQztBQUFBLFFBQzVFLFdBQVcsV0FBVyw0QkFBNEIsc0JBQXNCO0FBQ3RFLGdCQUFNLElBQUksTUFBTSwyRkFBMkY7QUFBQSxRQUM3RztBQUVBLFlBQ0UsbUJBQW1CLEtBQ25CLE9BQU8sU0FBUyxvQkFDaEIsT0FBTyxnQkFBZ0IsRUFBRSxLQUFLLFdBQVcsS0FDekMsT0FBTyxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsSUFBSSxHQUNuQztBQUNBLGlCQUFPLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLFFBQVEsQ0FBQyxVQUFVLE9BQU8sS0FBSyxLQUFLLENBQUM7QUFDaEYsY0FDRSxPQUFPLFdBQVcsS0FDbEIsT0FBTyxXQUFXLFFBQ2xCLGdCQUFnQixNQUNoQixPQUFPLFdBQVcsV0FBVyxLQUFLLFFBQ2xDO0FBQ0Esa0JBQU0sSUFBSSxNQUFNLDZGQUE2RjtBQUFBLFVBQy9HO0FBQ0EseUJBQWUsUUFBUSxVQUFVO0FBQ2pDLGNBQUksV0FBVyxLQUFLLFNBQVMsR0FBRztBQUM5Qix5QkFBYSxRQUFRLFdBQVcsTUFBTSxJQUFJLEVBQUUsUUFBUSxDQUFDLE9BQU8sVUFBVyxPQUFPLEtBQUssSUFBSSxLQUFNO0FBQUEsVUFDL0Y7QUFBQSxRQUNGO0FBQ0EsWUFDRSxrQkFBa0IsS0FDbEIsT0FBTyxTQUFTLG1CQUNoQixPQUFPLGVBQWUsRUFBRSxLQUFLLFdBQVcsS0FDeEMsT0FBTyxlQUFlLEVBQUUsS0FBSyxDQUFDLElBQUksR0FDbEM7QUFDQSxpQkFBTyxlQUFlLEVBQUUsaUJBQWlCLEVBQUUsUUFBUSxDQUFDLFVBQVUsTUFBTSxLQUFLLE9BQU8sS0FBSyxDQUFDLENBQUM7QUFDdkYsY0FBSSxNQUFNLFdBQVcsS0FBSyxNQUFNLFdBQVcsUUFBUSxnQkFBZ0IsTUFBTSxNQUFNLFdBQVcsV0FBVyxLQUFLLFFBQVE7QUFDaEgsa0JBQU0sSUFBSSxNQUFNLDRGQUE0RjtBQUFBLFVBQzlHO0FBQUEsUUFDRjtBQUVBLFlBQUksV0FBVyxLQUFLLFNBQVMsR0FBRztBQUM5QixjQUFJLE9BQU8sV0FBVyxLQUFLLE9BQU8sV0FBVyxXQUFXLEtBQUssUUFBUTtBQUNuRSxrQkFBTSxJQUFJLE1BQU0sMEZBQTBGO0FBQUEsVUFDNUc7QUFDQSxjQUFJLE1BQU0sV0FBVyxLQUFLLE1BQU0sV0FBVyxXQUFXLEtBQUssUUFBUTtBQUNqRSxrQkFBTSxJQUFJLE1BQU0sOEZBQThGO0FBQUEsVUFDaEg7QUFBQSxRQUNGO0FBQ0EsWUFBSSxPQUFPLFdBQVcsZUFBZSxPQUFPLFVBQVUsZUFBZSxPQUFPLFNBQVMsS0FBSyxNQUFNLFNBQVMsTUFBTTtBQUM3RyxnQkFBTSxJQUFJLE1BQU0seURBQXlEO0FBQUEsUUFDM0U7QUFBQSxNQUNGO0FBRUEsTUFBTSx5QkFBeUIsQ0FBQyxHQUFXLEdBQVcsR0FBVyxVQUEwQjtBQUFBO0FBQUE7QUFBQTtBQUFBLGVBSTVFLENBQUMsUUFBUSxDQUFDO0FBQUEsZ0JBQ1QsS0FBSyxXQUFXLENBQUM7QUFBQSxnQkFDakIsS0FBSyxXQUFXLENBQUMsUUFBUSxLQUFLLElBQUksQ0FBQztBQUFBO0FBQUE7QUFJbkQsTUFBTSw2Q0FBNkMsQ0FDakQsd0JBQ0EsVUFFQTtBQUFBLDJEQUN5RCxLQUFLLFNBQzdELE1BQU07QUFDTCxnQkFBUSx3QkFBd0I7QUFBQSxVQUM5QixLQUFLO0FBQ0gsbUJBQU87QUFBQTtBQUFBLHFCQUVNLEtBQUssZ0JBQWdCLEtBQUs7QUFBQTtBQUFBLGNBRWpDLHVCQUF1QixZQUFZLGtCQUFrQixpQkFBaUIsS0FBSyxDQUFDO0FBQUE7QUFBQTtBQUFBLFVBR3BGLEtBQUs7QUFDSCxtQkFBTztBQUFBLDhCQUNlLEtBQUssdUJBQXVCLEtBQUs7QUFBQTtBQUFBO0FBQUE7QUFBQSxVQUl6RCxLQUFLO0FBQ0gsbUJBQU8sV0FBVyxLQUFLLHVCQUF1QixLQUFLO0FBQUEsVUFDckQsS0FBSztBQUNILG1CQUFPO0FBQUE7QUFBQTtBQUFBLHNCQUdPLHVCQUF1QixZQUFZLHNCQUFzQixxQkFBcUIsS0FBSyxDQUFDO0FBQUE7QUFBQSxVQUVwRyxLQUFLO0FBQ0gsbUJBQU87QUFBQSw2QkFDYyxLQUFLLGdCQUFnQixLQUFLO0FBQUEsMkJBQzVCLEtBQUssZ0JBQWdCLEtBQUsseUJBQXlCLEtBQUs7QUFBQSwwQkFDekQsS0FBSztBQUFBO0FBQUEsbUNBRUksS0FBSyx5QkFBeUIsS0FBSztBQUFBO0FBQUEsVUFFaEUsS0FBSztBQUNILG1CQUFPLHVCQUF1QixLQUFLLFlBQVksS0FBSztBQUFBLHVDQUNyQixLQUFLO0FBQUEsbUNBQ1QsS0FBSztBQUFBO0FBQUEsc0NBRUYsS0FBSyx1QkFBdUIsS0FBSztBQUFBLFVBQ2pFLEtBQUs7QUFDSCxtQkFBTyxZQUFZLEtBQUssdUJBQXVCLEtBQUs7QUFBQSxVQUN0RDtBQUNFLGtCQUFNLElBQUksTUFBTSw2QkFBNkIsc0JBQXNCLG1CQUFtQjtBQUFBLFFBQzFGO0FBQUEsTUFDRixHQUFHLElBQ0g7QUFFRixNQUFNLDhCQUE4QixDQUFDLGFBQTBCLGNBQXNCLFVBQ25GLDZDQUE2QyxLQUFLLDRCQUE0QixLQUFLLFFBQ2xGLE1BQU07QUFDTCxnQkFBUSxhQUFhO0FBQUEsVUFDbkIsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFLVCxLQUFLO0FBQ0gsbUJBQU87QUFBQSxVQUNULEtBQUs7QUFDSCxtQkFBTztBQUFBLFVBQ1QsS0FBSztBQUNILG1CQUFPO0FBQUEsVUFLVCxLQUFLO0FBQUEsVUFDTDtBQUNFLGdCQUFJLGVBQWUsSUFBSTtBQUNyQixxQkFBTztBQUFBLFlBTVQ7QUFDQSxrQkFBTSxJQUFJLE1BQU0sZ0JBQWdCLFdBQVcsbUJBQW1CO0FBQUEsUUFDbEU7QUFBQSxNQUNGLEdBQUcsSUFDSDtBQUVGLE1BQU0sWUFBWSxDQUFDLEtBQXdCLE1BQXlCLFNBQTJCO0FBQzdGLGNBQU0sU0FBUyxJQUFJLE1BQU0sSUFBSSxFQUFFLEtBQUssQ0FBQyxFQUFFLE9BQU8sSUFBSSxNQUFNLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNyRSxjQUFNLFdBQVcsSUFBSSxXQUFXLElBQUksU0FBUyxJQUFJLE1BQU07QUFDdkQsWUFBSSxLQUFLLFNBQVMsR0FBRztBQUNuQixlQUFLLFFBQVEsQ0FBQyxHQUFHLE1BQU07QUFDckIsbUJBQU8sQ0FBQyxJQUFJLFNBQVMsQ0FBQztBQUN0QixtQkFBTyxJQUFJLElBQUksSUFBSSxTQUFTLEtBQUssU0FBUyxDQUFDO0FBQUEsVUFDN0MsQ0FBQztBQUNELGlCQUFPO0FBQUEsUUFDVDtBQUNBLGVBQU87QUFBQSxNQUNUO0FBRUEsTUFBTSxrQkFBa0IsQ0FDdEIsWUFDQSxRQUNBLE9BQ0EsU0FDYTtBQUNiLFlBQUksY0FBd0IsQ0FBQztBQUM3QixZQUFJLE1BQU0sU0FBUyxHQUFHO0FBQ3BCLGNBQUksS0FBSyxTQUFTLEdBQUc7QUFDbkIsdUJBQVcsUUFBUSxDQUFDLE1BQU0sWUFBWSxLQUFLLENBQUMsQ0FBQztBQUM3QyxnQkFBSSxLQUFLLElBQUksR0FBRyxJQUFJLElBQUksV0FBVyxRQUFRO0FBQ3pDLG9CQUFNLElBQUksTUFBTSxzQkFBc0I7QUFBQSxZQUN4QztBQUNBLGlCQUFLLFFBQVEsQ0FBQyxHQUFHLE1BQU8sWUFBWSxDQUFDLElBQUksTUFBTSxDQUFDLENBQUU7QUFBQSxVQUNwRCxPQUFPO0FBQ0wsa0JBQU0sUUFBUSxDQUFDLE1BQU0sWUFBWSxLQUFLLENBQUMsQ0FBQztBQUFBLFVBQzFDO0FBQUEsUUFDRixPQUFPO0FBQ0wsY0FBSSxPQUFPLFdBQVcsR0FBRztBQUN2QixrQkFBTSxJQUFJLE1BQU0seUNBQXlDO0FBQUEsVUFDM0QsT0FBTztBQUNMLDBCQUFjLFdBQVcsSUFBSSxDQUFDLE9BQU8sVUFBVSxLQUFLLE1BQU0sUUFBUSxPQUFPLEtBQUssQ0FBQyxDQUFDO0FBQUEsVUFDbEY7QUFBQSxRQUNGO0FBQ0EsZUFBTztBQUFBLE1BQ1Q7QUFFQSxNQUFNLG9CQUFvQixDQUFDLFlBQStCLFFBQWtCLGVBQWlDO0FBQzNHLGNBQU0saUJBQWlCLE1BQU07QUFDM0Isa0JBQVEsV0FBVyx1QkFBdUI7QUFBQSxZQUN4QyxLQUFLO0FBQ0gscUJBQU8sV0FBVyxLQUFLLFNBQVMsSUFDNUIsS0FBSyxJQUFJLEdBQUcsV0FBVyxLQUFLLElBQUksQ0FBQyxNQUFNLE9BQU8sQ0FBQyxDQUFDLEdBQUcsT0FBTyxTQUFTLElBQ25FLEtBQUssSUFBSSxHQUFHLFFBQVEsT0FBTyxTQUFTO0FBQUEsWUFDMUMsS0FBSztBQUNILHFCQUFPLFdBQVcsS0FBSyxTQUFTLElBQzVCLEtBQUssSUFBSSxHQUFHLFdBQVcsS0FBSyxJQUFJLENBQUMsTUFBTSxPQUFPLENBQUMsQ0FBQyxHQUFHLE9BQU8sU0FBUyxJQUNuRSxLQUFLLElBQUksR0FBRyxRQUFRLE9BQU8sU0FBUztBQUFBLFlBQzFDO0FBQ0Usb0JBQU0sSUFBSSxNQUFNLDRCQUE0QixXQUFXLHFCQUFxQixtQkFBbUI7QUFBQSxVQUNuRztBQUFBLFFBQ0YsR0FBRztBQUNILGVBQU8sS0FBSyxHQUFLLEdBQUcsT0FBTyxNQUFNO0FBQ2pDLGNBQU0sc0JBQXNCLFdBQVcsTUFBTTtBQUM3QyxZQUFJLFdBQVcsS0FBSyxTQUFTLEdBQUc7QUFDOUIscUJBQVcsS0FBSyxRQUFRLENBQUMsTUFBTyxPQUFPLENBQUMsSUFBSSxhQUFjO0FBQzFELHFCQUFXLEtBQUssUUFBUSxDQUFDLE1BQU8sb0JBQW9CLENBQUMsSUFBSSxLQUFLLE1BQU0sV0FBVyxDQUFDLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBRTtBQUFBLFFBQ2pHLE9BQU87QUFDTCxpQkFBTyxLQUFLLGVBQWUsR0FBRyxPQUFPLE1BQU07QUFDM0MsOEJBQW9CLFFBQVEsQ0FBQyxHQUFHLE1BQU8sb0JBQW9CLENBQUMsSUFBSSxLQUFLLE1BQU0sSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFFO0FBQUEsUUFDNUY7QUFDQSxlQUFPO0FBQUEsTUFDVDtBQUVBLE1BQU0sNENBQTRDLENBQ2hELFFBQ0EsWUFDQSxhQUNBLGNBQ0EsY0FDVztBQUFBLG1FQUNzRCxPQUFPLEtBQUssT0FBTyxjQUNoRixPQUFPLEtBQUssS0FDZCxLQUFLLFlBQVksTUFBTTtBQUFBLG9DQUNTLE9BQU8sS0FBSyxLQUFLLEtBQUssWUFBWSxNQUFNO0FBQUEsZ0NBQzVDLFlBQVksTUFBTTtBQUFBLDZCQUNyQixPQUFPLFdBQVcsa0JBQWtCLEdBQUcsQ0FBQztBQUFBLHNCQUMvQyxhQUFhLG1CQUFtQixLQUFLLFlBQVksQ0FBQztBQUFBLHdCQUNoRCxhQUFhLGdCQUFnQixLQUFLLFNBQVMsQ0FBQztBQUFBLHVCQUM3QyxhQUFhLGdCQUFnQixPQUFPLFdBQVcsTUFBTSxJQUFJLFNBQVMsQ0FBQztBQUFBO0FBQUEsa0NBRXhELE9BQU8sS0FBSyxLQUFLO0FBQUE7QUFBQSxnQ0FFbkIsYUFBYSx3QkFBd0IsS0FBSyxXQUFXLE1BQU0sQ0FBQztBQUFBLGlDQUMzRCxhQUFhLHlCQUF5QixLQUFLLFlBQVksTUFBTSxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBUS9GLE1BQU0seUNBQXlDLENBQzdDLE9BQ0EsUUFDQSxZQUNBLGFBQ0EsY0FDQSxXQUNBLHFCQUNXO0FBQUEsZ0VBQ21ELE9BQU8sS0FBSyxPQUFPLFFBQVEsTUFBTSxLQUFLLE9BQU87QUFBQSwyQkFDbEYsTUFBTSxLQUFLLE9BQU87QUFBQSxnQ0FDYixZQUFZLE1BQU07QUFBQSw2QkFDckIsT0FBTyxXQUFXLGtCQUFrQixHQUFHLENBQUM7QUFBQTtBQUFBLHNCQUUvQyxhQUFhLG1CQUFtQixLQUFLLFlBQVksQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBLDBCQUk5QyxhQUFhLGdCQUFnQixLQUFLLFNBQVMsQ0FBQztBQUFBLHlCQUM3QyxhQUFhLGdCQUFnQixPQUFPLFdBQVcsTUFBTSxJQUFJLFNBQVMsQ0FBQztBQUFBLGdDQUM1RCxhQUFhLHdCQUF3QixLQUFLLFdBQVcsTUFBTSxDQUFDO0FBQUEsaUNBQzNELGFBQWEseUJBQXlCLEtBQUssWUFBWSxNQUFNLENBQUM7QUFBQTtBQUFBO0FBQUEsaUJBRzlFLGdCQUFnQiw0Q0FBNEMsT0FBTyxLQUFLLEtBQUs7QUFBQTtBQUFBO0FBQUEsd0NBR3RELE9BQU8sS0FBSyxLQUFLO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFVBUy9DLE1BQU0sV0FBVyxpQkFBaUIsS0FBSyxhQUFhLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFJL0QsTUFBTSxvQkFBb0IsQ0FBQyxPQUFzQixlQUEwQztBQUFBLDBDQUNqRCxNQUFNLEtBQUssT0FBTztBQUFBLGdDQUM1QixXQUFXLE1BQU07QUFBQSw0QkFDckIsTUFBTSxXQUFXLGlCQUFpQixHQUFHLENBQUM7QUFBQSxnREFDbEIsYUFBYSx3QkFBd0IsS0FBSyxXQUFXLE1BQU0sQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFPNUcsTUFBTSw0QkFBNEIsQ0FDaEMsT0FDQSxZQUNBLFVBQ0EsZ0JBRUEsTUFBTSxPQUFPLGNBQ1Q7QUFBQSxNQUNBLE1BQU0sV0FBVyxpQkFBaUIsWUFBWSxTQUFTLENBQUM7QUFBQSxNQUN4RCxNQUFNLFdBQVcsaUJBQWlCLFVBQVUsT0FBTyxDQUFDO0FBQUEsSUFFcEQ7QUFFTixNQUFNLHdCQUF3QixDQUM1QixPQUNBLFFBQ0EsWUFDQSxrQkFDQSx1QkFDVztBQUNYLGNBQU0sU0FBUztBQUNmLGNBQU0sQ0FBQyxVQUFVLFdBQVcsVUFBVSxVQUFVLElBQzlDLFdBQVcsV0FBVyxJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsRUFBRSxJQUFJLFNBQVMsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO0FBQ2hGLGNBQU0sUUFBUSxNQUFNLEtBQUs7QUFDekIsZUFBTztBQUFBLHdFQUMrRCxLQUFLO0FBQUEsMkJBQ2xELE1BQU0sS0FBSyxPQUFPO0FBQUEsUUFDckMsTUFBTSxXQUFXLGlCQUFpQixXQUFXLG1CQUFtQixXQUFXLFNBQVMsQ0FBQyxRQUFRLENBQUM7QUFBQSxRQUM5RixNQUFNLFdBQVcsaUJBQWlCLFVBQVUsbUJBQW1CLFdBQVcsUUFBUSxDQUFDLFFBQVEsQ0FBQztBQUFBLFFBQzVGLDBCQUEwQixPQUFPLFlBQVksVUFBVSxDQUFDLENBQUM7QUFBQSxlQUNsRCxNQUFNLGFBQWEsZUFBZSxDQUFDO0FBQUE7QUFBQTtBQUFBLCtDQUdILE9BQU8sS0FBSyxPQUFPLFFBQVEsS0FBSztBQUFBO0FBQUEsZ0JBRS9ELEtBQUssc0JBQXNCLFNBQVM7QUFBQSxnQkFDcEMsS0FBSyxzQkFBc0IsUUFBUTtBQUFBLFFBRTNDLG1CQUNJLHlCQUF5QixXQUFXLFNBQVMsQ0FBQyw4QkFBOEIsV0FBVyxRQUFRLENBQUM7QUFBQSxpQkFDM0Ysa0JBQWtCO0FBQUEsV0FFdkIsRUFDTjtBQUFBLDhCQUN3QixXQUFXLFNBQVMsQ0FBQztBQUFBLDhCQUNyQixXQUFXLFFBQVEsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsMkJBS3ZCLFdBQVcsU0FBUyxJQUFJLHVCQUF1QixVQUFVLE9BQU8sR0FBRztBQUFBLDBCQUNwRSxXQUFXLFNBQVMsSUFBSSx1QkFBdUIsUUFBUSxPQUFPLEdBQUc7QUFBQSxpQkFDMUUsS0FBSztBQUFBLGlCQUNMLEtBQUs7QUFBQSxpQkFDTCxLQUFLO0FBQUEsaUJBQ0wsS0FBSztBQUFBLGlCQUNMLEtBQUssZ0JBQWdCLEtBQUs7QUFBQSxpQkFDMUIsS0FBSyxVQUFVLEtBQUs7QUFBQSxpQkFDcEIsS0FBSyxnQkFBZ0IsS0FBSztBQUFBLGlCQUMxQixLQUFLLFVBQVUsS0FBSztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsTUFXckM7QUFFQSxNQUFNLHVCQUF1QixDQUMzQixPQUNBLFFBQ0EsWUFDQSxhQUNBLFFBQ0EsS0FDQSxhQUNBLGtCQUNBLG9CQUNBLG1CQUNXO0FBQ1gsY0FBTSxPQUFPLFdBQVcsV0FBVztBQUNuQyxjQUFNLFNBQVM7QUFDZixjQUFNLENBQUMsV0FBVyxRQUFRLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztBQUNyRSxjQUFNLFFBQVEsTUFBTSxLQUFLO0FBQ3pCLGNBQU0sbUNBQW1DLENBQUMsUUFBd0I7QUFDaEUsZ0JBQU0sWUFBWSxRQUFRLFlBQVksUUFBUTtBQUM5QyxpQkFBTztBQUFBLFdBQ0EsU0FBUyxxQ0FBcUMsTUFBTSxLQUFLLE9BQU8scUJBQ25FLE9BQU8sS0FBSyxPQUNkLFFBQVEsS0FBSztBQUFBLDZCQUNVLE9BQU8sV0FBVyxrQkFBa0IsR0FBRyxDQUFDO0FBQUEsMkJBQzFDLEtBQUssK0RBQStELE9BQU8sR0FBRyxDQUFDO0FBQUEsVUFDaEcsWUFBWSxHQUFHLENBQUMsS0FBSyxXQUFXLEdBQUcsQ0FBQyxLQUFLLElBQUksR0FBRyxDQUFDLEtBQUssSUFBSSxHQUFHLENBQUMsTUFBTSxXQUFXLE1BQU07QUFBQSxnQ0FDL0QsS0FBSztBQUFBO0FBQUE7QUFBQSxjQUd2QixnQkFBZ0IsMENBQTBDLFdBQVcsR0FBRyxDQUFDO0FBQUEsbUJBQ3BFLGtCQUFrQjtBQUFBO0FBQUEsMEJBRVgsS0FBSyxnQkFBZ0IsS0FBSztBQUFBO0FBQUEsZ0JBRXBDLFNBQVMsS0FBSyxLQUFLLG9CQUFvQixLQUFLO0FBQUEsZ0JBQzVDLFNBQVMsV0FBVyxTQUFTLE9BQU8sV0FBVyxHQUFHLENBQUM7QUFBQSxlQUNwRCxNQUFNO0FBQ1AsZ0JBQUksZ0JBQWdCO0FBQ2xCLHFCQUFPO0FBQUE7QUFBQSxZQUVULFdBQVcsa0JBQWtCO0FBQzNCLHFCQUFPLFVBQVUsa0JBQWtCO0FBQUEsWUFDckMsT0FBTztBQUNMLHFCQUFPLEdBQUcsU0FBUyxpQkFBaUIsU0FBUyxLQUFLLFdBQVcsR0FBRyxDQUFDO0FBQUEsWUFDbkU7QUFBQSxVQUNGLEdBQUcsQ0FBQztBQUFBO0FBQUEsa0NBRWtCLE1BQU0sS0FBSyxPQUFPO0FBQUEsWUFDeEMsTUFBTSxXQUFXLHNCQUFzQixLQUFLLE9BQU8sU0FBUyxHQUFHLENBQUM7QUFBQSwwQkFFaEUsUUFBUSxZQUNKLE1BQU0sYUFBYSxvQkFBb0IsSUFDdkMsMkRBQ047QUFBQTtBQUFBO0FBQUE7QUFBQSxRQUlSO0FBRUEsZUFBTztBQUFBLE1BQ0gsaUNBQWlDLFNBQVMsQ0FBQztBQUFBLE1BQzNDLGlDQUFpQyxRQUFRLENBQUM7QUFBQSxxQ0FDWCxLQUFLLGNBQWMsS0FBSztBQUFBO0FBQUEsd0JBRXJDLEtBQUssZ0JBQWdCLEtBQUs7QUFBQSx3QkFDMUIsS0FBSztBQUFBLHdCQUNMLEtBQUs7QUFBQSx1QkFDTixLQUFLO0FBQUEsb0JBQ1IsV0FBVyx3QkFBd0IsV0FBVyx5QkFDNUQsV0FDRix5QkFBeUIsV0FBVztBQUFBLG9CQUNwQixXQUFXLG1CQUFtQixXQUFXO0FBQUEsb0JBQ3pDLFdBQVcsMkJBQTJCLFdBQVc7QUFBQSxvQkFDakQsV0FBVyx5QkFBeUIsV0FBVywwQkFDN0QsV0FDRiwwQkFBMEIsV0FBVztBQUFBO0FBQUE7QUFBQTtBQUFBLHFDQUlKLEtBQUssc0JBQXNCLEtBQUssWUFBWSxLQUFLO0FBQUEsb0JBQ2xFLEtBQUs7QUFBQTtBQUFBO0FBQUE7QUFBQSw0Q0FJbUIsT0FBTyxLQUFLLE9BQU8sUUFBUSxLQUFLO0FBQUEseUJBQ25ELE1BQU0sS0FBSyxPQUFPO0FBQUE7QUFBQTtBQUFBO0FBQUEsTUFJM0M7QUFFQSxNQUFNLHlCQUF5QixDQUM3QixPQUNBLFFBQ0EsWUFDQSxrQkFDQSx1QkFDVztBQUNYLGNBQU0sU0FBUztBQUNmLGNBQU0sQ0FBQyxVQUFVLFVBQVUsV0FBVyxVQUFVLFVBQVUsSUFDeEQsV0FBVyxXQUFXLElBQUksQ0FBQyxJQUFJLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxTQUFTLENBQUMsR0FBRyxHQUFHLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxHQUFHLENBQUM7QUFDekYsY0FBTSxRQUFRLE1BQU0sS0FBSztBQUN6QixlQUFPO0FBQUEsd0ZBQytFLEtBQUs7QUFBQSwyQkFDbEUsTUFBTSxLQUFLLE9BQU87QUFBQSxRQUNyQyxNQUFNLFdBQVcsaUJBQWlCLFVBQVUscUJBQXFCLFdBQVcsUUFBUSxDQUFDLFFBQVEsQ0FBQztBQUFBLFFBQzlGLE1BQU0sV0FBVyxpQkFBaUIsV0FBVyxzQkFBc0IsV0FBVyxTQUFTLENBQUMsUUFBUSxDQUFDO0FBQUEsUUFDakcsTUFBTSxXQUFXLGlCQUFpQixVQUFVLHFCQUFxQixXQUFXLFFBQVEsQ0FBQyxRQUFRLENBQUM7QUFBQSxRQUM5RiwwQkFBMEIsT0FBTyxZQUFZLFVBQVUsQ0FBQyxDQUFDO0FBQUEsZUFDbEQsTUFBTSxhQUFhLGVBQWUsQ0FBQztBQUFBO0FBQUE7QUFBQSxnREFHRixPQUFPLEtBQUssT0FBTyxRQUFRLEtBQUs7QUFBQTtBQUFBLGtCQUU5RCxLQUFLLHNCQUFzQixRQUFRO0FBQUEsbUJBQ2xDLEtBQUssc0JBQXNCLFNBQVM7QUFBQSxrQkFDckMsS0FBSyxzQkFBc0IsUUFBUTtBQUFBLFFBRTdDLG1CQUNJLDZCQUE2QixXQUFXLFFBQVEsQ0FBQyxvQ0FDL0MsV0FBVyxTQUFTLENBQ3RCLGtDQUFrQyxXQUFXLFFBQVEsQ0FBQztBQUFBLGVBQ25ELGtCQUFrQjtBQUFBLGFBRXJCLEVBQ047QUFBQTtBQUFBLGdDQUUwQixXQUFXLFFBQVEsQ0FBQztBQUFBLG9DQUNoQixXQUFXLFNBQVMsQ0FBQztBQUFBLGtDQUN2QixXQUFXLFFBQVEsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLDJCQU8zQixXQUFXLFNBQVMsSUFBSSx1QkFBdUIsVUFBVSxPQUFPLEdBQUc7QUFBQSwwQkFDcEUsV0FBVyxTQUFTLElBQUksdUJBQXVCLFFBQVEsT0FBTyxHQUFHO0FBQUE7QUFBQSxrQkFFekUsS0FBSztBQUFBLGtCQUNMLEtBQUs7QUFBQSxrQkFDTCxLQUFLO0FBQUEsa0JBQ0wsS0FBSztBQUFBLGtCQUNMLEtBQUs7QUFBQSxrQkFDTCxLQUFLO0FBQUEsa0JBQ0wsS0FBSztBQUFBLGtCQUNMLEtBQUs7QUFBQSxpQkFDTixLQUFLLGtCQUFrQixLQUFLO0FBQUEsaUJBQzVCLEtBQUssVUFBVSxLQUFLO0FBQUEsaUJBQ3BCLEtBQUssbUJBQW1CLEtBQUs7QUFBQSxpQkFDN0IsS0FBSyxVQUFVLEtBQUs7QUFBQSxpQkFDcEIsS0FBSyxrQkFBa0IsS0FBSztBQUFBLGlCQUM1QixLQUFLLFVBQVUsS0FBSztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE1BZ0JyQztBQUVBLE1BQU0sMEJBQTBCLENBQzlCLGFBQ0EsWUFDQSxjQUNBLGFBQ0EsT0FDQSxhQUNnQjtBQUNoQixjQUFNLGFBQWEsWUFBWTtBQUMvQixjQUFNLE1BQU0sVUFBVSxVQUFVLFdBQVcsTUFBTSxXQUFXLE1BQU07QUFFbEUsWUFBSSxjQUFjLGdCQUFnQixZQUFZLGFBQWEsT0FBTyxXQUFXLElBQUk7QUFDakYsWUFBSSxTQUFTLFlBQVksTUFBTTtBQUMvQixZQUFJLFlBQVksV0FBVyxHQUFHO0FBQzVCLG1CQUFTLFdBQVcsSUFBSSxDQUFDLE9BQU8sVUFBVyxVQUFVLElBQUksSUFBTSxZQUFZLEtBQUssSUFBSSxLQUFNO0FBQzFGLGNBQUksV0FBVywwQkFBMEIsV0FBVztBQUNsRCwwQkFBYyxrQkFBa0IsWUFBWSxRQUFRLFVBQVU7QUFBQSxVQUNoRTtBQUFBLFFBQ0Y7QUFDQSxjQUFNLFNBQVMsZUFBZSxVQUFVLFlBQVksVUFBVSxZQUFZLE1BQU07QUFDaEYsY0FBTSxRQUFRLGNBQWMsU0FBUyxZQUFZLFVBQVUsV0FBVyxNQUFNO0FBQzVFLGNBQU0sYUFBYSxVQUFVLEtBQUssV0FBVztBQUM3QyxjQUFNLFVBQVUsV0FBVyxXQUFXLFlBQVksVUFBVSxXQUFXLE1BQU0sQ0FBQyxHQUFHLE1BQU0sTUFBTSxZQUFZLENBQUMsQ0FBQztBQUMzRyxjQUFNLG1CQUFtQixXQUFXLDRCQUE0QjtBQUNoRSxjQUFNLHFCQUFxQixXQUFXO0FBQ3RDLGNBQU0sV0FBVyxNQUFNLEtBQUs7QUFDNUIsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFBQSxRQUVsRCxVQUNJLEtBQ0E7QUFBQSxRQUNKLDJDQUEyQyxXQUFXLHlCQUF5QixRQUFRLENBQUM7QUFBQSxTQUN2RixNQUFNO0FBQ1Asa0JBQVEsV0FBVyxNQUFNO0FBQUEsWUFDdkIsS0FBSztBQUNILHFCQUFPO0FBQUEsZ0JBQ0gsa0JBQWtCLE9BQU8sVUFBVSxDQUFDO0FBQUEsZ0JBQ3BDLDRCQUE0QixXQUFXLGFBQWEsY0FBYyxRQUFRLENBQUM7QUFBQSxnQkFDM0U7QUFBQSxnQkFDQTtBQUFBLGdCQUNBO0FBQUEsZ0JBQ0E7QUFBQSxnQkFDQTtBQUFBLGdCQUNBLE9BQU87QUFBQSxnQkFDUCxJQUFJO0FBQUEsZ0JBQ0o7QUFBQSxjQUNGLENBQUM7QUFBQTtBQUFBLFlBRUwsS0FBSztBQUNILHFCQUFPO0FBQUEsZ0JBQ0gsMENBQTBDLFFBQVEsWUFBWSxhQUFhLE9BQU8sUUFBUSxJQUFJLE1BQU0sQ0FBQztBQUFBLGlCQUNwRyxNQUFNO0FBQ1Asb0JBQUksV0FBVyxXQUFXLEtBQUssV0FBVyxXQUFXLEdBQUc7QUFDdEQseUJBQU8sR0FBRyxzQkFBc0IsT0FBTyxRQUFRLFlBQVksa0JBQWtCLGtCQUFrQixDQUFDO0FBQUEsZ0JBQ2xHLFdBQVcsV0FBVyxXQUFXLEtBQUssV0FBVyxXQUFXLEdBQUc7QUFDN0QseUJBQU8sR0FBRyx1QkFBdUIsT0FBTyxRQUFRLFlBQVksa0JBQWtCLGtCQUFrQixDQUFDO0FBQUEsZ0JBQ25HLE9BQU87QUFDTCx3QkFBTSxNQUFNLGtGQUFrRjtBQUFBLGdCQUNoRztBQUFBLGNBQ0YsR0FBRyxDQUFDO0FBQUE7QUFBQSxZQUVSLEtBQUs7QUFDSCxxQkFBTztBQUFBLGVBQ0osTUFBTTtBQUNQLG9CQUFJLFdBQVcsV0FBVyxLQUFLLFdBQVcsV0FBVyxHQUFHO0FBQ3RELHlCQUFPLEdBQUc7QUFBQSxvQkFDUjtBQUFBLG9CQUNBO0FBQUEsb0JBQ0E7QUFBQSxvQkFDQTtBQUFBLG9CQUNBO0FBQUEsb0JBQ0E7QUFBQSxvQkFDQSxXQUFXO0FBQUEsb0JBQ1g7QUFBQSxvQkFDQSxXQUFXO0FBQUEsb0JBQ1gsV0FBVztBQUFBLGtCQUNiLENBQUM7QUFBQSxnQkFDSCxPQUFPO0FBQ0wsd0JBQU0sTUFBTSwyRUFBMkU7QUFBQSxnQkFDekY7QUFBQSxjQUNGLEdBQUcsQ0FBQztBQUFBO0FBQUEsWUFFTjtBQUNFLG9CQUFNLE1BQU0scUJBQXFCO0FBQUEsVUFDckM7QUFBQSxRQUNGLEdBQUcsQ0FBQztBQUFBLE9BRUo7QUFBQSxRQUNFLGFBQ0MsZ0JBQWdCLGVBQWUsS0FBSyxFQUNwQyxnQkFBZ0IsVUFBVSxPQUFPLE9BQU8sTUFBTSxFQUM5QyxnQkFBZ0IsT0FBTyxPQUFPLElBQUksTUFBTSxFQUN4QyxpQkFBaUIsT0FBTyxNQUFNLENBQUM7QUFBQSxRQUNoQyxhQUFhLFVBQVUsQ0FBQztBQUFBLFVBQ3RCLGFBQWEsc0NBQXNDLHNCQUFzQixDQUFDO0FBQUEsVUFFMUUsVUFDSSw0Q0FDQTtBQUFBLCtCQUNpQixPQUFPLGdCQUFnQixZQUFZLENBQUM7QUFBQSw2QkFDdEMsTUFBTSxLQUFLLE9BQU87QUFBQSxXQUNwQyxNQUFNO0FBQ1Asa0JBQVEsV0FBVyxNQUFNO0FBQUEsWUFDdkIsS0FBSztBQUNILHFCQUFPO0FBQUE7QUFBQSx5Q0FFb0IsTUFBTSxhQUFhLGVBQWUsQ0FBQztBQUFBO0FBQUEseUNBRW5DLFdBQVcsa0JBQWtCO0FBQUE7QUFBQSxZQUUxRCxLQUFLO0FBQ0gscUJBQU8sd0JBQ0wsV0FBVyxXQUFXLEtBQUssV0FBVyxXQUFXLElBQUksMEJBQTBCLHdCQUNqRjtBQUFBLFlBQ0YsS0FBSztBQUNILHFCQUFPO0FBQUEsWUFDVDtBQUNFLG9CQUFNLE1BQU0sNEJBQTRCLFdBQVcsSUFBSSxFQUFFO0FBQUEsVUFDN0Q7QUFBQSxRQUNGLEdBQUcsQ0FBQztBQUFBLENBRUo7QUFBQTtBQUdOLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWE7QUFBQSxZQUNYLE1BQU0sR0FBRyxXQUFXLFFBQVEsSUFBSSxZQUFZLElBQzFDLE9BQU8sU0FBUyxJQUFLLFdBQVcsU0FBUyxVQUFVLFNBQVMsT0FBTyxTQUFVLEVBQy9FLElBQUksTUFBTSxTQUFTLElBQUksUUFBUSxFQUFFLElBQUksSUFBSSxTQUFTLElBQUksTUFBTSxFQUFFLElBQUksT0FBTyxJQUN2RSxXQUFXLFNBQVMsWUFBWSxXQUFXLFNBQVMsVUFDdEQ7QUFBQSxZQUNBLG1CQUFtQixDQUFDLE1BQU07QUFBQSxVQUM1QjtBQUFBLFVBQ0E7QUFBQSxVQUNBLFlBQVksT0FBTztBQUFBLFlBQ2pCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sYUFBYSxVQUFVLFlBQVksU0FBUyxDQUFDO0FBQUEsWUFDL0QsZUFBZSxFQUFFLEdBQUcsS0FBSztBQUFBLGNBQUssYUFBYTtBQUFBO0FBQUEsWUFBdUIsRUFBRTtBQUFBLFlBQ3BFLGlCQUFpQjtBQUFBLGNBQ2YsRUFBRSx1QkFBdUIsTUFBTSxXQUFXO0FBQUEsY0FDMUMsRUFBRSxxQkFBc0IsTUFBTSxPQUFPO0FBQUEsY0FDckMsRUFBRSxxQkFBc0IsTUFBTSxJQUFJO0FBQUEsY0FDbEMsR0FBRywyQkFBMkIsWUFBWSxXQUFXO0FBQUEsWUFDdkQ7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFQSxNQUFNLHNDQUFzQyxDQUFDLFlBQW9DO0FBQy9FLGNBQU0sbUJBQW1CLFFBQVE7QUFDakMsY0FBTSxxQkFBcUIsSUFBSSxZQUFZLGtCQUFrQixpQkFBaUIsWUFBWSxDQUFDO0FBQzNGLGNBQU0sZUFBZSxtQkFBbUIsQ0FBQztBQUN6QyxlQUFPO0FBQUEsTUFDVDtBQUVPLE1BQU0sU0FBUyxDQUFDLFNBQXlCLGVBQXVDO0FBQ3JGLGNBQU0sU0FBbUIsQ0FBQztBQUMxQixjQUFNLFFBQWtCLENBQUM7QUFDekIsY0FBTSxNQUFnQixDQUFDO0FBS3ZCLGNBQU0sZUFBZSxvQ0FBb0MsT0FBTztBQUNoRSxZQUFJLFdBQVcsY0FBYyxHQUFHO0FBQzlCLGdCQUFNLE1BQU0sNkRBQTZEO0FBQUEsUUFDM0U7QUFDQSxRQUFBQSxpQkFBZSxRQUFRLFFBQVEsWUFBWSxjQUFjLFFBQVEsT0FBTyxHQUFHO0FBQzNFLGdCQUFRLFFBQVEsd0JBQXdCLFFBQVEsT0FBTyxDQUFDLEdBQUcsWUFBWSxjQUFjLFFBQVEsT0FBTyxHQUFHLEdBQUc7QUFBQSxVQUN4RyxRQUFRLENBQUMsQ0FBQztBQUFBLFFBQ1osQ0FBQztBQUFBLE1BQ0g7QUFFTyxNQUFNLHdCQUF3QixDQUFDLGVBQTBEO0FBQzlGLGNBQU0sWUFBWSxXQUFXO0FBQzdCLGNBQU0sT0FBTyxXQUFXO0FBQ3hCLGNBQU0sMEJBQ0osV0FBVztBQUNiLGNBQU0sY0FBYyxXQUFXO0FBQy9CLGNBQU0saUJBQWtCLFdBQVcsbUJBQThCO0FBQ2pFLGNBQU0scUJBQXFCLFdBQVc7QUFDdEMsY0FBTSx3QkFBK0MsV0FBVztBQUNoRSxjQUFNLE9BQWEsV0FBVztBQUU5QixjQUFNLGNBQTRCLFdBQVcsZ0JBQWdCLEtBQUssV0FBVyxXQUFXO0FBQ3hGLGVBQU8sNEJBQTRCO0FBQUEsVUFDakM7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFFBQ0YsQ0FBQztBQUFBLE1BQ0g7QUFBQTtBQUFBOzs7QUN2MEJBLE1Bd0JNQyxrQkF3REEsZ0NBOElPO0FBOU5iO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFHQTtBQWdCQSxNQUFNQSxtQkFBaUIsQ0FBQyxXQUF3QztBQUM5RCxZQUFJLENBQUMsVUFBVSxPQUFPLFNBQVMsR0FBRztBQUNoQyxnQkFBTSxJQUFJLE1BQU0sdUNBQXVDO0FBQUEsUUFDekQ7QUFFQSxjQUFNLFFBQW9CLE9BQU8sQ0FBQztBQUNsQyxjQUFNLE9BQW1CLE9BQU8sQ0FBQztBQUNqQyxjQUFNLFFBQW9CLE9BQU8sQ0FBQztBQUVsQyxZQUFJLE1BQU0sYUFBYSxLQUFLLFlBQVksTUFBTSxhQUFhLE1BQU0sVUFBVTtBQUN6RSxnQkFBTSxJQUFJLE1BQU0seUNBQXlDO0FBQUEsUUFDM0Q7QUFFQSxZQUFJLE1BQU0sS0FBSyxXQUFXLEtBQUssTUFBTSxLQUFLLFdBQVcsR0FBRztBQUN0RCxnQkFBTSxJQUFJLE1BQU0sd0JBQXdCO0FBQUEsUUFDMUM7QUFFQSxZQUFJLEtBQUssS0FBSyxXQUFXLEtBQUssS0FBSyxLQUFLLFdBQVcsR0FBRztBQUNwRCxnQkFBTSxJQUFJLE1BQU0sdUJBQXVCO0FBQUEsUUFDekM7QUFFQSxjQUFNLGFBQWEsTUFBTSxLQUFLLE1BQU0sS0FBSyxTQUFTLENBQUM7QUFDbkQsY0FBTSxpQkFBaUIsTUFBTSxLQUFLLE1BQU0sS0FBSyxTQUFTLENBQUM7QUFDdkQsWUFBSSxLQUFLLEtBQUssS0FBSyxLQUFLLFNBQVMsQ0FBQyxNQUFNLFlBQVk7QUFDbEQsZ0JBQU0sSUFBSSxNQUFNLDhDQUE4QztBQUFBLFFBQ2hFO0FBQ0EsWUFBSSxLQUFLLEtBQUssS0FBSyxLQUFLLFNBQVMsQ0FBQyxNQUFNLGdCQUFnQjtBQUN0RCxnQkFBTSxJQUFJLE1BQU0sa0RBQWtEO0FBQUEsUUFDcEU7QUFFQSxZQUFJLE1BQU0sS0FBSyxXQUFXLEdBQUc7QUFDM0IsZ0JBQU0sSUFBSSxNQUFNLGtCQUFrQjtBQUFBLFFBQ3BDO0FBQ0EsWUFBSSxNQUFNLEtBQUssTUFBTSxLQUFLLFNBQVMsQ0FBQyxNQUFNLFlBQVk7QUFDcEQsZ0JBQU0sSUFBSSxNQUFNLCtDQUErQztBQUFBLFFBQ2pFO0FBQ0EsWUFBSSxPQUFPLFNBQVMsR0FBRztBQUNyQixnQkFBTSxPQUFtQixPQUFPLENBQUM7QUFDakMsY0FBSSxLQUFLLEtBQUssV0FBVyxHQUFHO0FBQzFCLGtCQUFNLElBQUksTUFBTSxpQkFBaUI7QUFBQSxVQUNuQztBQUNBLGNBQUksS0FBSyxLQUFLLEtBQUssS0FBSyxTQUFTLENBQUMsTUFBTSxZQUFZO0FBQ2xELGtCQUFNLElBQUksTUFBTSw4Q0FBOEM7QUFBQSxVQUNoRTtBQUFBLFFBQ0Y7QUFDQSxZQUFJLE9BQU8sU0FBUyxHQUFHO0FBQ3JCLGdCQUFNLE9BQW1CLE9BQU8sQ0FBQztBQUNqQyxjQUFJLEtBQUssS0FBSyxXQUFXLEdBQUc7QUFDMUIsa0JBQU0sSUFBSSxNQUFNLGlCQUFpQjtBQUFBLFVBQ25DO0FBQ0EsY0FBSSxLQUFLLEtBQUssS0FBSyxLQUFLLFNBQVMsQ0FBQyxNQUFNLFlBQVk7QUFDbEQsa0JBQU0sSUFBSSxNQUFNLDhDQUE4QztBQUFBLFVBQ2hFO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFQSxNQUFNLGlDQUFpQyxDQUNyQyxRQUNBLFlBQ0EsYUFDQSxlQUNnQjtBQUNoQixjQUFNLGFBQWEsV0FBVztBQUU5QixjQUFNLGFBQWEsT0FBTyxDQUFDLEVBQUU7QUFDN0IsY0FBTSxZQUFZLFVBQVUsS0FBSyxVQUFVO0FBQzNDLGNBQU0sY0FBYztBQUNwQixjQUFNLGFBQWE7QUFDbkIsY0FBTSxhQUFhLFdBQVcsTUFBTSxFQUFFLEVBQUUsQ0FBQztBQUN6QyxjQUFNLG1CQUFtQixhQUFhLFdBQVcsTUFBTSxHQUFHLEVBQUUsRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDO0FBQzNFLGNBQU0sZUFBZSxDQUFDLGNBQWMsT0FBTyxTQUFTO0FBQ3BELGNBQU0sZUFBZSxPQUFPLFNBQVM7QUFDckMsY0FBTSxnQkFBZ0IsY0FBYyxjQUFjO0FBQ2xELGNBQU0scUJBQXFCLGNBQWMsY0FBYztBQUN2RCxjQUFNLDRCQUE0QixjQUFjO0FBQ2hELGNBQU0sZ0JBQWdCO0FBRXRCLGNBQU0sYUFBYSxpQkFBaUIsVUFBVTtBQUU5QyxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUscUJBQXNCLE1BQU0sV0FBVyxRQUFRO0FBQUEsUUFDbkQ7QUFDQSxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUN0RCxnQkFBTSxnQkFBbUM7QUFBQSxZQUN2QyxFQUFFLE1BQU0sZUFBZSxNQUFNLE1BQU07QUFBQSxZQUNuQyxFQUFFLE1BQU0sY0FBYyxNQUFNLE1BQU07QUFBQSxZQUNsQyxFQUFFLE1BQU0sZUFBZSxNQUFNLE1BQU07QUFBQSxZQUNuQyxFQUFFLE1BQU0sV0FBVyxNQUFNLE1BQU07QUFBQSxVQUNqQztBQUNBLGdCQUFNLFlBQVk7QUFBQSxZQUNoQixjQUFjLEtBQUssT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxNQUFNLFVBQVU7QUFBQSxZQUNqRSxjQUFjLFFBQVEsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxNQUFNLFVBQVU7QUFBQSxZQUNwRSxjQUFjLFNBQVMsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxNQUFNLFVBQVU7QUFBQSxVQUN2RTtBQUNBLGNBQUksY0FBYztBQUNoQixzQkFBVSxLQUFLLGNBQWMsUUFBUSxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQUEsVUFDdEY7QUFDQSxjQUFJLGNBQWM7QUFDaEIsc0JBQVUsS0FBSyxjQUFjLFFBQVEsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUFBLFVBQ3RGO0FBQ0Esb0JBQVUsS0FBSyxlQUFlLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxhQUFhLFVBQVUsQ0FBQztBQUNwRixjQUFJLGVBQWU7QUFDakIsc0JBQVUsS0FBSyxlQUFlLDhCQUErQixnQkFBZ0IsQ0FBQztBQUFBLFVBQ2hGO0FBQ0EsY0FBSSxvQkFBb0I7QUFDdEIsc0JBQVUsS0FBSyxlQUFlLGlDQUFrQyxnQkFBZ0IsQ0FBQztBQUFBLFVBQ25GO0FBQ0EsY0FBSSwyQkFBMkI7QUFDN0Isc0JBQVUsS0FBSyxlQUFlLHVCQUF1QixPQUFPLENBQUMsRUFBRSxVQUFVLGFBQWEsVUFBVSxDQUFDO0FBQUEsVUFDbkc7QUFDQSxnQkFBTSxXQUFXLDRCQUE0QixPQUFPLENBQUMsRUFBRSxRQUFRO0FBQy9ELGdCQUFNLGNBQWMsMkNBQTRDLFVBQVU7QUFDMUUsaUJBQU87QUFBQTtBQUFBLFFBRUgsYUFBYSxpQkFBaUIsYUFBYSxFQUFFLGlCQUFpQixHQUFHLFNBQVMsQ0FBQztBQUFBLDBDQUN6QyxXQUFXLEtBQUssYUFBYTtBQUFBLGtEQUNyQixXQUFXLEtBQUssYUFBYTtBQUFBO0FBQUEsUUFFdkUsYUFBYSxVQUFVLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQUE7QUFBQSxpQ0FFcEIsYUFBYTtBQUFBO0FBQUE7QUFBQSxnREFHRSxhQUFhO0FBQUE7QUFBQTtBQUFBLG9CQUd6QyxnQkFBZ0IsQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsNkJBS1IsZUFBZSx1QkFBdUIsV0FBVyxPQUFPO0FBQUE7QUFBQTtBQUFBLFlBR3pFLDRCQUE0Qiw2Q0FBNkMsRUFBRTtBQUFBO0FBQUEsNEJBRTNELFVBQVUsVUFBVSxZQUFZLE9BQU8sQ0FBQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxrQ0FNbEMsYUFBYTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxxQkFZMUIsVUFBVSxPQUFPLFVBQVUsQ0FBQztBQUFBLHdDQUNULFVBQVUsY0FBYyxVQUFVLENBQUMsZ0NBQ2pFLGFBQWEsS0FBSyxlQUNwQjtBQUFBLFVBQ0UsZ0JBQWdCLG9DQUFvQyxFQUFFO0FBQUEsVUFDdEQscUJBQXFCLDhDQUE4QyxFQUFFO0FBQUE7QUFBQTtBQUFBLHFEQUcxQixhQUFhLEtBQUssS0FBSyxRQUFRLFFBQVE7QUFBQSxjQUM5RSxRQUFRO0FBQUEsY0FDUixlQUFlLHlCQUF5QixFQUFFO0FBQUE7QUFBQTtBQUFBLFFBR3REO0FBQ0EsY0FBTSxVQUFVLENBQUMsRUFBRSxNQUFNLGFBQWEsVUFBVSxPQUFPLENBQUMsRUFBRSxTQUFTLENBQUM7QUFDcEUsWUFBSSxjQUFjLEdBQUc7QUFDbkIsa0JBQVEsS0FBSyxFQUFFLE1BQU0sa0JBQWtCLHdCQUF5QixDQUFDO0FBQUEsUUFDbkU7QUFDQSxZQUFJLGNBQWMsR0FBRztBQUNuQixrQkFBUSxLQUFLLEVBQUUsTUFBTSxrQkFBa0Isd0JBQXlCLENBQUM7QUFBQSxRQUNuRTtBQUNBLFlBQUksY0FBYyxHQUFHO0FBQ25CLGtCQUFRLEtBQUssRUFBRSxNQUFNLFlBQVksVUFBVSxPQUFPLENBQUMsRUFBRSxTQUFTLENBQUM7QUFBQSxRQUNqRTtBQUNBLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWE7QUFBQSxZQUNYLE1BQU0sR0FBRyxVQUFVLElBQUksYUFBYSxJQUFJLGtCQUFrQixJQUFJLHlCQUF5QjtBQUFBLFlBQ3ZGLG1CQUFtQixPQUFPLElBQUksQ0FBQyxRQUFRLFdBQVcsTUFBTTtBQUFBLFVBQzFEO0FBQUEsVUFDQTtBQUFBLFVBQ0EsWUFBWSxPQUFPO0FBQUEsWUFDakI7QUFBQSxZQUNBLGVBQWU7QUFBQSxjQUNiLEdBQUcsS0FBSyxLQUFLLGFBQWEsVUFBVTtBQUFBLFlBQ3RDO0FBQUEsWUFDQTtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sZ0JBQWdCLENBQUMsU0FBeUIsZUFBOEM7QUFFbkcsY0FBTSxhQUFhO0FBQ25CLFFBQUFBLGlCQUFlLFFBQVEsTUFBTTtBQUc3QixjQUFNLFVBQVUsQ0FBQyxDQUFDO0FBQ2xCLFlBQUksUUFBUSxjQUFjLEdBQUc7QUFDM0Isa0JBQVEsS0FBSyxhQUFhLElBQUksRUFBRTtBQUFBLFFBQ2xDO0FBQ0EsWUFBSSxRQUFRLGNBQWMsR0FBRztBQUMzQixrQkFBUSxLQUFLLGFBQWEsSUFBSSxFQUFFO0FBQUEsUUFDbEM7QUFDQSxZQUFJLFFBQVEsY0FBYyxHQUFHO0FBQzNCLGtCQUFRLEtBQUssQ0FBQztBQUFBLFFBQ2hCO0FBQ0EsZ0JBQVEsUUFBUSwrQkFBK0IsUUFBUSxRQUFRLFlBQVksUUFBUSxhQUFhLFVBQVUsR0FBRztBQUFBLFVBQzNHO0FBQUEsUUFDRixDQUFDO0FBQUEsTUFDSDtBQUFBO0FBQUE7OztBQ2pQQSxNQXlCTUMsa0JBa0JBLFdBY0EsaUNBaUJBLG1CQWtCQSwyQkF5QkEsd0JBNkZPLE9BWUE7QUE5TmI7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUNBO0FBR0E7QUFnQkEsTUFBTUEsbUJBQWlCLENBQUMsUUFBK0IsZUFBc0M7QUFDM0YsWUFBSSxDQUFDLFVBQVUsT0FBTyxTQUFTLEdBQUc7QUFDaEMsZ0JBQU0sSUFBSSxNQUFNLGdCQUFnQjtBQUFBLFFBQ2xDO0FBQ0EsWUFBSSxXQUFXLEtBQUssV0FBVyxHQUFHO0FBQ2hDLGNBQUksV0FBVyxLQUFLLFdBQVcsV0FBVyxPQUFPLFVBQVUsV0FBVyxLQUFLLFdBQVcsV0FBVyxLQUFLLFFBQVE7QUFDNUcsa0JBQU0sSUFBSSxNQUFNLGlEQUFpRDtBQUFBLFVBQ25FO0FBQUEsUUFDRixXQUFXLFdBQVcsT0FBTyxXQUFXLFdBQVcsS0FBSyxRQUFRO0FBQzlELGdCQUFNLElBQUksTUFBTSwyQ0FBMkM7QUFBQSxRQUM3RDtBQUNBLGVBQU8sTUFBTSxDQUFDLEVBQUUsUUFBUSxDQUFDLEdBQUcsUUFBUTtBQUNsQyxjQUFJLE9BQU8sTUFBTSxDQUFDLEVBQUUsOEJBQStCLE9BQU8sTUFBTSxDQUFDLEVBQUUsNEJBQTZCO0FBQzlGLGtCQUFNLElBQUksTUFBTSxTQUFTLEdBQUcscUNBQXFDO0FBQUEsVUFDbkU7QUFBQSxRQUNGLENBQUM7QUFBQSxNQUNIO0FBRUEsTUFBTSxZQUFZLENBQUMsUUFBK0IsUUFBMEI7QUFDMUUsY0FBTSxRQUFrQixDQUFDO0FBQ3pCLFlBQUksT0FBTyxTQUFTLEtBQUs7QUFDdkIsY0FBSSxPQUFPLEdBQUcsRUFBRSw0QkFBNkI7QUFDM0MsbUJBQU8sR0FBRyxFQUFFLGlCQUFpQixFQUFFLFFBQVEsQ0FBQyxNQUFNLE1BQU0sS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDO0FBQUEsVUFDckUsV0FBVyxPQUFPLEdBQUcsRUFBRSw0QkFBNkI7QUFDbEQsbUJBQU8sR0FBRyxFQUFFLGNBQWMsRUFBRSxRQUFRLENBQUMsTUFBTSxNQUFNLEtBQUssT0FBTyxDQUFDLENBQUMsQ0FBQztBQUFBLFVBQ2xFLE9BQU87QUFDTCxrQkFBTSxJQUFJLE1BQU0sU0FBUyxHQUFHLHFDQUFxQztBQUFBLFVBQ25FO0FBQUEsUUFDRjtBQUNBLGVBQU87QUFBQSxNQUNUO0FBRUEsTUFBTSxrQ0FBa0MsQ0FDdEMsUUFDQSxlQUNvQjtBQUNwQixZQUFJLE9BQU8sU0FBUyxHQUFHO0FBQ3JCLGdCQUFNLFNBQW1CLFVBQVUsUUFBUSxDQUFDO0FBQzVDLGdCQUFNLE9BQWlCLFVBQVUsUUFBUSxDQUFDO0FBQzFDLGNBQUksT0FBaUIsVUFBVSxRQUFRLENBQUM7QUFDeEMsY0FBSSxLQUFLLFdBQVcsR0FBRztBQUNyQixtQkFBTyxDQUFDLEdBQUcsTUFBTSxPQUFPLENBQUMsRUFBRSxLQUFLLE1BQU0sRUFBRSxLQUFLLENBQUM7QUFBQSxVQUNoRDtBQUNBLGlCQUFPLDRCQUE0QixFQUFFLFFBQVEsTUFBTSxLQUFLLENBQUM7QUFBQSxRQUMzRCxPQUFPO0FBQ0wsaUJBQU87QUFBQSxRQUNUO0FBQUEsTUFDRjtBQUVBLE1BQU0sb0JBQW9CLENBQ3hCLE9BQ0EsT0FDQSxZQUNBLE1BQ0EsVUFDVztBQUNYLFlBQUksV0FBVztBQUNmLFlBQUksUUFBUSxHQUFHO0FBQ2Isc0JBQVksV0FBVyxLQUFLLEtBQUssQ0FBQztBQUFBLFFBQ3BDO0FBQ0EsWUFBSSxNQUFNLEtBQUssSUFBSSxHQUFHO0FBQ3BCLGlCQUFPLEtBQUssSUFBSSxHQUFHLEtBQUssSUFBSSxVQUFVLFdBQVcsS0FBSyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7QUFBQSxRQUNwRSxPQUFPO0FBQ0wsaUJBQU8sS0FBSyxJQUFJLEdBQUcsS0FBSyxJQUFJLFVBQVUsV0FBVyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFBQSxRQUNoRTtBQUFBLE1BQ0Y7QUFFQSxNQUFNLDRCQUE0QixDQUNoQyxPQUNBLFFBQ0EsZUFFQSw0Q0FBNEMsT0FBTyxLQUFLLE9BQU8sUUFBUSxNQUFNLEtBQUssT0FBTztBQUFBLCtCQUM1RCxNQUFNLEtBQUssT0FBTztBQUFBO0FBQUEseUJBRXhCLFdBQVcsTUFBTTtBQUFBLGtDQUNSLGFBQWEsd0JBQXdCLEtBQUssV0FBVyxNQUFNLENBQUM7QUFBQSw0QkFDbEUsYUFBYSxrQkFBa0IsS0FBSyxXQUFXLE1BQU0sQ0FBQztBQUFBLDRCQUN0RCxhQUFhLGtCQUFrQixLQUFLLFdBQVcsTUFBTSxDQUFDO0FBQUEsNkJBQ3JELGFBQWEsbUJBQW1CLEtBQUssV0FBVyxNQUFNLENBQUM7QUFBQSxpQ0FDbkQsT0FBTyxXQUFXLGtCQUFrQixHQUFHLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxjQU8zRCxNQUFNLFdBQVcsaUJBQWlCLEtBQUssYUFBYSxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBS25FLE1BQU0seUJBQXlCLENBQUMsUUFBK0IsZUFBNkM7QUFDMUcsY0FBTSxhQUFhLE9BQU8sQ0FBQyxFQUFFO0FBQzdCLGNBQU0sWUFBWSxVQUFVLEtBQUssVUFBVTtBQUMzQyxjQUFNLE9BQ0osV0FBVyxLQUFLLFNBQVMsSUFDckIsVUFBVSxjQUFjLFdBQVcsTUFBTSxXQUFXLE1BQU0sSUFDMUQsQ0FBQyxHQUFHLE1BQU0sV0FBVyxNQUFNLEVBQUUsS0FBSyxDQUFDO0FBQ3pDLFlBQUksUUFBUSxVQUFVLFFBQVEsQ0FBQztBQUMvQixjQUFNO0FBQUEsVUFDSixDQUFDLFNBQ0MsU0FBUyxNQUNSLE1BQU07QUFDTCxrQkFBTSxJQUFJLE1BQU0sa0JBQWtCO0FBQUEsVUFDcEM7QUFBQSxRQUNKO0FBQ0EsWUFBSSxNQUFNLFdBQVcsR0FBRztBQUN0QixrQkFBUSxNQUFNLEtBQUssTUFBTSxFQUFFLEtBQUssQ0FBQztBQUFBLFFBQ25DO0FBQ0EsY0FBTSxTQUFTLFdBQVcsT0FBTyxJQUFJLENBQUMsT0FBTyxNQUFNLGtCQUFrQixPQUFPLEdBQUcsWUFBWSxNQUFNLEtBQUssQ0FBQztBQUV2RyxjQUFNLE9BQU8sV0FBVyxLQUFLLElBQUksQ0FBQyxLQUFLLE1BQU0sa0JBQWtCLEtBQUssR0FBRyxZQUFZLE1BQU0sS0FBSyxDQUFDO0FBRS9GLFlBQUksS0FBSyxXQUFXLE9BQU8sVUFBVSxLQUFLLFdBQVcsS0FBSyxRQUFRO0FBQ2hFLGdCQUFNLElBQUksTUFBTSw4REFBOEQ7QUFBQSxRQUNoRjtBQUVBLFlBQUksS0FBSyxXQUFXLFdBQVcsUUFBUTtBQUNyQyxtQkFBUyxJQUFJLEdBQUcsSUFBSSxXQUFXLFFBQVEsRUFBRSxHQUFHO0FBQzFDLGdCQUFJLENBQUMsS0FBSyxTQUFTLENBQUMsR0FBRztBQUNyQixxQkFBTyxPQUFPLEdBQUcsR0FBRyxDQUFDO0FBQ3JCLG1CQUFLLE9BQU8sR0FBRyxHQUFHLFdBQVcsQ0FBQyxDQUFDO0FBQy9CLG9CQUFNLE9BQU8sR0FBRyxHQUFHLENBQUM7QUFBQSxZQUN0QjtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQ0EsY0FBTSxRQUFRLE1BQU0sSUFBSSxDQUFDLFNBQVMsS0FBSyxLQUFLLElBQUksQ0FBQztBQUVqRCxjQUFNLFFBQVEsQ0FBQyxNQUFNLEdBQUcsVUFBVTtBQUNoQyxjQUFJLE9BQU8sR0FBRztBQUNaLGtCQUFNLFlBQVksS0FBSyxDQUFDLElBQUksT0FBTyxDQUFDLEtBQUs7QUFDekMsa0JBQU0sU0FBUyxPQUFPLENBQUM7QUFDdkIsa0JBQU0sV0FBVyxTQUFTLFdBQVcsTUFBTSxDQUFDO0FBQzVDLG1CQUFPLENBQUMsSUFBSTtBQUNaLGlCQUFLLENBQUMsSUFBSTtBQUNWLGtCQUFNLENBQUMsSUFBSSxDQUFDO0FBQUEsVUFDZDtBQUFBLFFBQ0YsQ0FBQztBQUVELGNBQU0sY0FBYyxXQUFXLE1BQU0sQ0FBQztBQUN0QyxhQUFLLFFBQVEsQ0FBQyxNQUFNLE1BQU07QUFDeEIsc0JBQVksSUFBSSxJQUFJLEtBQUssTUFBTSxLQUFLLElBQUksSUFBSSxPQUFPLElBQUksS0FBSyxNQUFNLElBQUksQ0FBQztBQUFBLFFBQ3pFLENBQUM7QUFDRCxjQUFNLG1CQUErQixFQUFFLE1BQU0sYUFBYSxVQUFVLE9BQU8sQ0FBQyxFQUFFLFNBQVM7QUFFdkYsY0FBTSxTQUFTLGVBQWUsVUFBVSxPQUFPLENBQUMsRUFBRSxVQUFVLFlBQVksTUFBTTtBQUM5RSxjQUFNLFFBQVEsY0FBYyxTQUFTLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxDQUFDLEVBQUUsS0FBSyxNQUFNO0FBQzlFLGNBQU0sYUFBYSxVQUFVLEtBQUssV0FBVztBQUM3QyxjQUFNLFdBQThCO0FBQUEsVUFDbEMsRUFBRSxNQUFNLGNBQWMsTUFBTSxNQUFNO0FBQUEsVUFDbEMsRUFBRSxNQUFNLFVBQVUsTUFBTSxPQUFPLFFBQVEsT0FBTyxPQUFPO0FBQUEsVUFDckQsRUFBRSxNQUFNLFNBQVMsTUFBTSxPQUFPLFFBQVEsTUFBTSxPQUFPO0FBQUEsVUFDbkQsRUFBRSxNQUFNLFNBQVMsTUFBTSxPQUFPLFFBQVEsTUFBTSxPQUFPO0FBQUEsUUFDckQ7QUFFQSxjQUFNLGtCQUFvQztBQUFBLFVBQ3hDLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLFVBQzFDLEVBQUUsdUJBQXVCLE1BQU0sT0FBTztBQUFBLFVBQ3RDLEVBQUUscUJBQXNCLE1BQU0sTUFBTTtBQUFBLFVBQ3BDLEVBQUUsdUJBQXVCLE1BQU0sTUFBTTtBQUFBLFVBQ3JDLEdBQUcsMkJBQTJCLE9BQU8sQ0FBQyxFQUFFLE1BQU0sV0FBVztBQUFBLFFBQzNEO0FBRUEsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFBQSxRQUNsRCxhQUFhLGlCQUFpQixRQUFRLEVBQUUsaUJBQWlCLE9BQU8sTUFBTSxDQUFDO0FBQUEsVUFDckUsMEJBQTBCLE9BQU8sUUFBUSxVQUFVLENBQUM7QUFBQSxVQUNwRCxhQUFhLFVBQVUsQ0FBQztBQUFBLFlBQ3RCLGFBQWEsc0NBQXNDLHFCQUFxQixDQUFDO0FBQUEsaUNBQ3BELE9BQU8sZ0JBQWdCLFlBQVksQ0FBQztBQUFBO0FBQUEsWUFFekQsT0FBTyxZQUFZLGNBQWMsTUFBTSxhQUFhLGVBQWUsQ0FBQyxDQUFDO0FBQUE7QUFFL0UsZUFBTztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sYUFBYSxFQUFFLE1BQU0sR0FBRyxNQUFNLE1BQU0sSUFBSSxPQUFPLE1BQU0sSUFBSSxNQUFNLE1BQU0sSUFBSSxtQkFBbUIsQ0FBQyxNQUFNLEVBQUU7QUFBQSxVQUNyRztBQUFBLFVBQ0EsWUFBWSxPQUFPO0FBQUEsWUFDakIsU0FBUyxDQUFDLGdCQUFnQjtBQUFBLFlBQzFCLGVBQWUsRUFBRSxHQUFHLEtBQUs7QUFBQSxjQUFLLFlBQVk7QUFBQTtBQUFBLFlBQXVCLEVBQUU7QUFBQSxZQUNuRTtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sUUFBUSxDQUFDLFNBQXlCLGVBQXNDO0FBQ25GLFFBQUFBLGlCQUFlLFFBQVEsUUFBUSxVQUFVO0FBQ3pDLGNBQU0sb0JBQW9CLGdDQUFnQyxRQUFRLFFBQVEsVUFBVTtBQUNwRixnQkFBUSxRQUFRLHVCQUF1QixRQUFRLFFBQVEsaUJBQWlCLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFBQSxNQU81RjtBQUVPLE1BQU0sdUJBQXVCLENBQUMsZUFBeUQ7QUFDNUYsY0FBTSxTQUFTLFdBQVc7QUFDMUIsY0FBTSxPQUFPLFdBQVc7QUFDeEIsY0FBTSxPQUFPLFdBQVc7QUFDeEIsZUFBTyw0QkFBNEIsRUFBRSxRQUFRLE1BQU0sS0FBSyxDQUFDO0FBQUEsTUFDM0Q7QUFBQTtBQUFBOzs7QUNuT0EsTUF1Qk1DLGtCQVVBLDBCQXNKTyxTQUtBO0FBNUxiO0FBQUE7QUFBQTtBQU9BO0FBRUE7QUFDQTtBQUVBO0FBRUE7QUFTQSxNQUFNQSxtQkFBaUIsQ0FBQyxXQUF3QztBQUM5RCxZQUFJLENBQUMsVUFBVSxPQUFPLFdBQVcsR0FBRztBQUNsQyxnQkFBTSxJQUFJLE1BQU0sOEJBQThCO0FBQUEsUUFDaEQ7QUFBQSxNQUNGO0FBTUEsTUFBTSwyQkFBMkIsQ0FBQyxTQUF5QixlQUFrQztBQUMzRixjQUFNLFFBQVEsUUFBUSxPQUFPLENBQUM7QUFDOUIsY0FBTSxhQUFhLE1BQU07QUFDekIsY0FBTSxhQUFhLFVBQVUsS0FBSyxVQUFVO0FBQzVDLGNBQU0sWUFBWSxXQUFXO0FBQzdCLGNBQU0sT0FBTyxVQUFVLGNBQWMsV0FBVyxNQUFNLFNBQVM7QUFDL0QsY0FBTSxzQkFBc0IsT0FBTyxXQUFXLFNBQVM7QUFDdkQsWUFBSTtBQUNKLFlBQUksT0FBaUIsQ0FBQztBQUV0QixZQUFJLHFCQUFxQjtBQUN2QixpQkFBTyxNQUFNLEtBQUssRUFBRSxRQUFRLFVBQVUsR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDO0FBQ3BELGVBQUssSUFBSSxJQUFJLFlBQVk7QUFDekIsZUFBSyxZQUFZLENBQUMsSUFBSTtBQUV0Qiw0QkFBa0IsUUFBUSxRQUFRLDJCQUEyQixPQUFPLElBQUksR0FBRztBQUFBLFlBQ3pFLFFBQVEsQ0FBQyxLQUFLO0FBQUEsWUFDZCxTQUFTLENBQUMsRUFBRTtBQUFBLFVBQ2QsQ0FBQyxFQUFFLENBQUM7QUFBQSxRQUNOLE9BQU87QUFDTCw0QkFBa0I7QUFBQSxRQUNwQjtBQUVBLGNBQU0sdUJBQXVCLGdCQUFnQjtBQUM3QyxjQUFNLE9BQU8scUJBQXFCLFlBQVksQ0FBQztBQUMvQyxjQUFNLE9BQU8sYUFBYTtBQUMxQixjQUFNLGFBQWEsaUJBQWlCLElBQUk7QUFDeEMsY0FBTSxhQUFhLE9BQU87QUFDMUIsWUFBSSxLQUFLO0FBRVQsWUFBSSxTQUFTLEdBQUc7QUFDZCxlQUFLO0FBQUEsUUFDUDtBQUNBLGNBQU0sWUFBWSxDQUFDLE1BQWNDLGdCQUF1QjtBQUN0RCxjQUFJQSxnQkFBZSxHQUFHO0FBQ3BCLG1CQUFPLFdBQVcsSUFBSSxPQUFPLElBQUksWUFBWSxJQUFJLE9BQU8sSUFBSTtBQUFBLFVBQzlELFdBQVdBLGdCQUFlLEdBQUc7QUFDM0IsbUJBQU8sT0FBTyxJQUFJLE9BQU8sSUFBSTtBQUFBLFVBQy9CLFdBQVdBLGdCQUFlLEdBQUc7QUFDM0IsbUJBQU8sV0FBVyxJQUFJLE9BQU8sSUFBSSxRQUFRLElBQUk7QUFBQSxVQUMvQztBQUVBLGlCQUFPO0FBQUEsUUFDVDtBQUNBLGNBQU0sSUFBSSxjQUFjLEtBQUssZ0JBQWdCLFVBQVUsZ0JBQWdCLE1BQU0sVUFBVTtBQUN2RixjQUFNLFNBQVMsZUFBZSxVQUFVLGdCQUFnQixVQUFVLGdCQUFnQixNQUFNLFVBQVU7QUFDbEcsY0FBTSxZQUFZLEVBQUUsS0FBSztBQUV6QixjQUFNLGdCQUNKLDRCQUE0QixnQkFBZ0IsUUFBUSxNQUFNLFFBQ3RELG1CQUFtQixTQUFTLHNCQUM1QixtQkFBbUIsU0FBUztBQUNsQyxjQUFNLGtCQUFrQixDQUFDLGlCQUErQjtBQUFBLHNDQUNwQixTQUFTO0FBQUEsc0NBQ1QsU0FBUztBQUFBLDRDQUNILFNBQVMsS0FBSyxFQUFFO0FBQUE7QUFBQSw0REFFQSxTQUFTO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnRUFLTCxTQUFTO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFJakUsYUFBYSxnQkFBZ0IsY0FBYyxLQUFLLEVBQUUsaUJBQWlCLEdBQUcsTUFBTSxDQUFDO0FBQUEsUUFDN0UsYUFBYSxVQUFVLEVBQUUsQ0FBQztBQUFBO0FBQUE7QUFBQSxxQkFHYixFQUFFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFVBTWIsYUFBYTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLDJCQW1CSSxTQUFTLElBQUksVUFBVSxtQkFBbUIsVUFBVSxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSwwQkFLdEQsU0FBUztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSwyQkFlUixTQUFTLElBQUksVUFBVSxtQkFBbUIsVUFBVSxDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBVTlFLGNBQU0sU0FBUyxRQUFRO0FBQUEsVUFDckI7QUFBQSxZQUNFLE1BQU07QUFBQTtBQUFBLFlBRU4sYUFBYSxFQUFFLE1BQU0sR0FBRyxVQUFVLElBQUksRUFBRSxJQUFJLG1CQUFtQixDQUFDLE1BQU0sRUFBRTtBQUFBLFlBQ3hFLFlBQVksT0FBTztBQUFBLGNBQ2pCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sc0JBQXNCLFVBQVUsZ0JBQWdCLFNBQVMsQ0FBQztBQUFBLGNBQzVFLGVBQWUsRUFBRSxHQUFHLEtBQUs7QUFBQSxjQUN6QixpQkFBaUIsQ0FBQyxFQUFFLHFCQUFzQixNQUFNLFdBQVcsQ0FBQztBQUFBLFlBQzlEO0FBQUEsWUFDQTtBQUFBLFVBQ0Y7QUFBQSxVQUNBO0FBQUEsWUFDRSxRQUFRLENBQUMsZUFBZTtBQUFBLFlBQ3hCLFNBQVMsQ0FBQyxzQkFBc0IsS0FBSyxDQUFDO0FBQUEsVUFDeEM7QUFBQSxRQUNGLEVBQUUsQ0FBQztBQUVILFlBQUkscUJBQXFCO0FBQ3ZCLGtCQUFRLFFBQVEsMkJBQTJCLFFBQVEsSUFBSSxHQUFHO0FBQUEsWUFDeEQsUUFBUSxDQUFDLE1BQU07QUFBQSxVQUNqQixDQUFDO0FBQUEsUUFDSDtBQUFBLE1BQ0Y7QUFFTyxNQUFNLFVBQVUsQ0FBQyxTQUF5QixlQUF3QztBQUN2RixRQUFBRCxpQkFBZSxRQUFRLE1BQU07QUFDN0IsaUNBQXlCLFNBQVMsVUFBVTtBQUFBLE1BQzlDO0FBRU8sTUFBTSx5QkFBeUIsQ0FBQyxlQUNyQyw0QkFBNEIsRUFBRSxNQUFNLFdBQVcsS0FBZSxDQUFDO0FBQUE7QUFBQTs7O0FDN0xqRSxNQVVNLFlBR0FFLGtCQTZCQUMsaUJBVU8sdUJBeUNBO0FBN0ZiO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFHQTtBQUVBLE1BQU0sYUFBYSxDQUFDLHNCQUNsQixNQUFNLEtBQUssa0JBQWtCLGlCQUFpQixHQUFHLE1BQU07QUFFekQsTUFBTUQsbUJBQWlCLENBQUMsV0FBd0M7QUFDOUQsWUFBSSxDQUFDLFVBQVUsT0FBTyxXQUFXLEdBQUc7QUFDbEMsZ0JBQU0sSUFBSSxNQUFNLHlCQUF5QjtBQUFBLFFBQzNDO0FBRUEsWUFDRSxPQUFPLENBQUMsRUFBRSw4QkFDVixPQUFPLENBQUMsRUFBRSxpQ0FDVixPQUFPLENBQUMsRUFBRSw4QkFDVixPQUFPLENBQUMsRUFBRSw4QkFDVjtBQUNBLGdCQUFNLElBQUksTUFBTSxnRUFBZ0U7QUFBQSxRQUNsRjtBQUVBLFlBQUksT0FBTyxDQUFDLEVBQUUsNEJBQTZCO0FBQ3pDLGdCQUFNLElBQUksTUFBTSxtREFBbUQ7QUFBQSxRQUNyRTtBQUVBLFlBQUksT0FBTyxDQUFDLEVBQUUsS0FBSyxXQUFXLEdBQUc7QUFDL0IsZ0JBQU0sSUFBSSxNQUFNLG9DQUFvQztBQUFBLFFBQ3REO0FBRUEsY0FBTSxVQUE2QixXQUFXLE9BQU8sQ0FBQyxDQUFDO0FBRXZELFlBQUksUUFBUSxXQUFXLE9BQU8sQ0FBQyxFQUFFLEtBQUssUUFBUTtBQUM1QyxnQkFBTSxJQUFJLE1BQU0sdUZBQXVGO0FBQUEsUUFDekc7QUFBQSxNQUNGO0FBRUEsTUFBTUMsa0JBQWlCLENBQUMsWUFBK0IsWUFBa0Q7QUFDdkcsY0FBTSxjQUF3QixDQUFDO0FBRS9CLGlCQUFTLElBQUksR0FBRyxJQUFJLFdBQVcsUUFBUSxFQUFFLEdBQUc7QUFDMUMsc0JBQVksS0FBSyxXQUFXLENBQUMsSUFBSSxRQUFRLENBQUMsQ0FBQztBQUFBLFFBQzdDO0FBRUEsZUFBTztBQUFBLE1BQ1Q7QUFFTyxNQUFNLHdCQUF3QixDQUFDLFFBQStCLFVBQWtDO0FBQ3JHLGNBQU0sYUFBYSxPQUFPLENBQUMsRUFBRTtBQUM3QixjQUFNLFVBQTZCLFNBQVMsT0FBTyxXQUFXLE9BQU8sQ0FBQyxDQUFDLElBQUk7QUFDM0UsY0FBTSxjQUFjQSxnQkFBZSxZQUFZLE9BQU87QUFDdEQsY0FBTSxhQUFhLFVBQVUsS0FBSyxXQUFXO0FBRTdDLGNBQU0sV0FBVyxPQUFPLENBQUMsRUFBRTtBQUMzQixjQUFNLFFBQVEsY0FBYyxTQUFTLFVBQVUsV0FBVyxNQUFNO0FBQ2hFLGNBQU0sU0FBUyxlQUFlLFVBQVUsVUFBVSxZQUFZLE1BQU07QUFFcEUsY0FBTSxrQkFBa0IsQ0FBQyxpQkFBK0I7QUFBQSwyQkFDL0IsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDO0FBQUEsUUFDL0MsYUFBYSxnQkFBZ0IsZUFBZSxLQUFLLEVBQUUsaUJBQWlCLE9BQU8sTUFBTSxDQUFDO0FBQUEsUUFDbEYsYUFBYSxVQUFVLENBQUM7QUFBQSxRQUN4QixhQUFhLHNDQUFzQyxzQkFBc0IsQ0FBQztBQUFBLDZCQUNyRCxPQUFPLGdCQUFnQixZQUFZLENBQUM7QUFBQSwyQkFDdEMsTUFBTSxLQUFLLE9BQU87QUFBQSw0QkFDakIsV0FBVyxNQUFNO0FBQUEsNEJBQ2pCLE1BQU0sV0FBVyx3QkFBd0IsR0FBRyxDQUFDO0FBQUEsZ0NBQ3pDLE9BQU8sV0FBVyxrQkFBa0IsR0FBRyxDQUFDO0FBQUE7QUFBQSxVQUU5RCxNQUFNLFdBQVcsaUJBQWlCLEtBQUssaUJBQWlCLENBQUM7QUFBQTtBQUFBLFFBRTNELE9BQU8sWUFBWSxjQUFjLE1BQU0sYUFBYSxlQUFlLENBQUMsQ0FBQztBQUFBO0FBRzNFLGVBQU87QUFBQSxVQUNMLE1BQU07QUFBQSxVQUNOLGFBQWEsRUFBRSxNQUFNLEdBQUcsT0FBTyxJQUFJLG1CQUFtQixDQUFDLE1BQU0sRUFBRTtBQUFBLFVBQy9ELFlBQVksT0FBTztBQUFBLFlBQ2pCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sYUFBYSxVQUFVLE9BQU8sQ0FBQyxFQUFFLFNBQVMsQ0FBQztBQUFBLFlBQzdELGVBQWUsRUFBRSxHQUFHLEtBQUs7QUFBQSxjQUFLLGFBQWE7QUFBQTtBQUFBLFlBQXVCLEVBQUU7QUFBQSxZQUNwRSxpQkFBaUI7QUFBQSxjQUNmLEVBQUUsdUJBQXVCLE1BQU0sV0FBVztBQUFBLGNBQzFDLEdBQUcsMkJBQTJCLE9BQU8sQ0FBQyxFQUFFLE1BQU0sV0FBVztBQUFBLFlBQzNEO0FBQUEsVUFDRjtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sT0FBTyxDQUFDLFlBQWtDO0FBQ3JELFFBQUFELGlCQUFlLFFBQVEsTUFBTTtBQUM3QixnQkFBUSxRQUFRLHNCQUFzQixRQUFRLE1BQU0sR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUFBLE1BQ3hFO0FBQUE7QUFBQTs7O0FDaEdBLE1BVU0sNEJBaUVBLDBCQXNDTztBQWpIYjtBQUFBO0FBQUE7QUFHQTtBQUVBO0FBR0E7QUFFQSxNQUFNLDZCQUE2QixDQUNqQyxjQUNBLFFBQ0EsWUFDQSxhQUNBLGVBQ0c7QUFDSCxjQUFNLFNBQVMsZUFBZSxlQUFlLFlBQVksV0FBVyxRQUFRLENBQUM7QUFDN0UsY0FBTSxJQUFJLGNBQWMsVUFBVSxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sQ0FBQyxFQUFFLEtBQUssUUFBUSxDQUFDO0FBQzlFLGNBQU0sSUFBSSxjQUFjLFVBQVUsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLENBQUMsRUFBRSxLQUFLLFFBQVEsQ0FBQztBQUM5RSxjQUFNLElBQUksY0FBYyxVQUFVLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxDQUFDLEVBQUUsS0FBSyxRQUFRLENBQUM7QUFFOUUsWUFBSTtBQUNKLGNBQU0sYUFBYSxDQUFDRSxJQUFXQyxJQUFXQyxPQUFjLFVBQVVELEVBQUMsS0FBS0QsRUFBQyxLQUFLRSxFQUFDO0FBQy9FLFlBQUksQ0FBQyxhQUFhO0FBQ2hCLHVCQUFhLE9BQU87QUFBQSxZQUNsQjtBQUFBLFlBQ0EsV0FBVyxFQUFFLFlBQVksWUFBWSxHQUFHLEVBQUUsWUFBWSxZQUFZLEdBQUcsRUFBRSxZQUFZLFlBQVksQ0FBQztBQUFBLFVBQ2xHO0FBQUEsUUFDRixPQUFPO0FBQ0wsZ0JBQU0sbUJBQW1CLENBQUMsUUFBZ0IsR0FBVyxXQUFXLE9BQU87QUFDckUsa0JBQU0sY0FBYyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQztBQUN2RCxrQkFBTSxjQUFjLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDO0FBRXZELGtCQUFNLGNBQWMsc0JBQXNCLENBQUMsNkJBQTZCLENBQUM7QUFDekUsbUJBQU87QUFBQSxnQ0FDbUIsQ0FBQyxNQUFNLE9BQU8sZ0JBQWdCLHFCQUFxQixDQUFDLEdBQUcsQ0FBQztBQUFBLDBCQUM5RCxDQUFDLE1BQU0sRUFBRSwyQkFBMkIsaUJBQWlCLENBQUMsSUFBSSxNQUFNLENBQUM7QUFBQSwwQkFDakUsQ0FBQyxNQUFNLEVBQUUsMkJBQTJCLGlCQUFpQixDQUFDLElBQUksTUFBTSxDQUFDO0FBQUEsMEJBQ2pFLENBQUMsTUFBTSxFQUFFLDJCQUEyQixpQkFBaUIsQ0FBQyxJQUFJLE1BQU0sQ0FBQztBQUFBLHlCQUNsRSxDQUFDLGNBQWMsQ0FBQztBQUFBLHlCQUNoQixDQUFDLGNBQWMsQ0FBQztBQUFBLHlCQUNoQixDQUFDLGNBQWMsQ0FBQztBQUFBLDZCQUNaLENBQUMsY0FBYyxDQUFDO0FBQUEsNkJBQ2hCLENBQUMsY0FBYyxDQUFDO0FBQUEsNkJBQ2hCLENBQUMsY0FBYyxDQUFDO0FBQUEsY0FDL0IsTUFBTSxJQUFJLENBQUMsT0FBTyxRQUFRLElBQUksV0FBVyxhQUFhLGFBQWEsV0FBVyxDQUFDO0FBQUE7QUFBQSxVQUV6RjtBQUNBLGNBQUksNkJBQThCO0FBQ2hDLHlCQUFhO0FBQUE7QUFBQSxjQUVMLGlCQUFpQixRQUFRLEdBQUcsS0FBSyxDQUFDO0FBQUEsY0FDbEMsaUJBQWlCLFFBQVEsR0FBRyxLQUFLLENBQUM7QUFBQSxjQUNsQyxpQkFBaUIsUUFBUSxHQUFHLEtBQUssQ0FBQztBQUFBLGNBQ2xDLGlCQUFpQixRQUFRLEdBQUcsS0FBSyxDQUFDO0FBQUE7QUFBQSxVQUU1QyxPQUFPO0FBQ0wseUJBQWE7QUFBQSxjQUNMLGlCQUFpQiwyQkFBMkIsQ0FBQyxDQUFDO0FBQUEsY0FDOUMsaUJBQWlCLDJCQUEyQixDQUFDLENBQUM7QUFBQSxjQUM5QyxpQkFBaUIsMkJBQTJCLENBQUMsQ0FBQztBQUFBLGNBQzlDLGlCQUFpQiwyQkFBMkIsQ0FBQyxDQUFDO0FBQUE7QUFBQSxVQUV4RDtBQUFBLFFBQ0Y7QUFFQSxlQUFPO0FBQUEsVUFDQyxhQUFhLGdCQUFnQixZQUFZLEtBQUssRUFBRSxpQkFBaUIsR0FBRyxHQUFHLEdBQUcsTUFBTSxDQUFDO0FBQUEsVUFDakYsYUFBYSxVQUFVLENBQUM7QUFBQSxVQUN4QixhQUFhLHNDQUFzQyxtQkFBbUIsQ0FBQztBQUFBLFVBQ3ZFLFVBQVU7QUFBQTtBQUFBLE1BRXBCO0FBRUEsTUFBTSwyQkFBMkIsQ0FBQyxXQUErQztBQUMvRSxjQUFNLFFBQVEsT0FBTyxDQUFDLEVBQUU7QUFDeEIsY0FBTSxRQUFRLE9BQU8sQ0FBQyxFQUFFO0FBQ3hCLGNBQU0sUUFBUSxPQUFPLENBQUMsRUFBRTtBQUN4QixjQUFNLGlCQUFpQixPQUFPLENBQUMsRUFBRTtBQUVqQyxjQUFNLGNBQWMsRUFBRSxVQUFVLFNBQVMsT0FBTyxLQUFLLEtBQUssVUFBVSxTQUFTLE9BQU8sS0FBSztBQUN6RixZQUFJLGNBQWM7QUFDbEIsWUFBSSxhQUFhLFVBQVUsS0FBSyxLQUFLO0FBR3JDLFlBQUksYUFBYTtBQUNmLGdCQUFNLGtCQUFrQixjQUFjLFVBQVUsY0FBYyxVQUFVLE9BQU8sT0FBTyxLQUFLLEdBQUksT0FBTyxLQUFLO0FBQzNHLGNBQUksQ0FBQyxpQkFBaUI7QUFDcEIsa0JBQU0sSUFBSSxNQUFNLDZDQUE2QztBQUFBLFVBQy9EO0FBQ0Esd0JBQWM7QUFDZCx1QkFBYSxVQUFVLEtBQUssV0FBVztBQUFBLFFBQ3pDO0FBRUEsY0FBTSxVQUFVLEtBQUssS0FBSyxhQUFhLENBQUM7QUFFeEMsZUFBTztBQUFBLFVBQ0wsTUFBTTtBQUFBLFVBQ04sYUFBYSxFQUFFLG1CQUFtQixDQUFDLFFBQVEsUUFBUSxNQUFNLEVBQUU7QUFBQSxVQUMzRCxpQkFBaUIsQ0FBQyxpQkFDaEIsMkJBQTJCLGNBQWMsUUFBUSxhQUFhLGFBQWEsY0FBYztBQUFBLFVBQzNGLFlBQVksT0FBTztBQUFBLFlBQ2pCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sYUFBYSxVQUFVLGVBQWUsQ0FBQztBQUFBLFlBQ3pELGVBQWUsRUFBRSxHQUFHLEtBQUs7QUFBQSxjQUFLLGFBQWEsS0FBMEI7QUFBQTtBQUFBLFlBQWdCLEVBQUU7QUFBQSxZQUN2RixpQkFBaUI7QUFBQSxjQUNmLEVBQUUsdUJBQXVCLE1BQU0sUUFBUTtBQUFBLGNBQ3ZDLEdBQUcsMkJBQTJCLE9BQU8sT0FBTyxPQUFPLFdBQVc7QUFBQSxZQUNoRTtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sUUFBUSxDQUFDLFlBQWtDO0FBQ3RELGdCQUFRLFFBQVEseUJBQXlCLFFBQVEsTUFBTSxDQUFDO0FBQUEsTUFDMUQ7QUFBQTtBQUFBOzs7QUNuSEEsTUE4RGE7QUE5RGI7QUFBQTtBQUFBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBT08sTUFBTSwwQkFBK0Qsb0JBQUksSUFBSTtBQUFBLFFBQ2xGLENBQUMsT0FBTyxDQUFVLEdBQUcsQ0FBQztBQUFBLFFBQ3RCLENBQUMsUUFBUSxDQUFVLElBQUksQ0FBQztBQUFBLFFBQ3hCLENBQUMsU0FBUyxDQUFVLEtBQUssQ0FBQztBQUFBLFFBQzFCLENBQUMsT0FBTyxDQUFXLEdBQUcsQ0FBQztBQUFBLFFBQ3ZCLENBQUMsVUFBVSxDQUFDLFFBQVEsd0JBQXdCLENBQUM7QUFBQSxRQUM3QyxDQUFDLFVBQVUsQ0FBQyxRQUFRLHdCQUF3QixDQUFDO0FBQUEsUUFDN0MsQ0FBQyxRQUFRLENBQVUsSUFBSSxDQUFDO0FBQUEsUUFDeEIsQ0FBQyxTQUFTLENBQVUsS0FBSyxDQUFDO0FBQUEsUUFDMUIsQ0FBQyxRQUFRLENBQVUsSUFBSSxDQUFDO0FBQUEsUUFDeEIsQ0FBQyxTQUFTLENBQVUsS0FBSyxDQUFDO0FBQUEsUUFDMUIsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDO0FBQUE7QUFBQSxRQUV6QixDQUFDLGVBQWUsQ0FBTSxhQUFrQiwwQkFBMEIsQ0FBQztBQUFBLFFBQ25FLENBQUMsc0JBQXNCLENBQUMsU0FBUyxDQUFDO0FBQUEsUUFDbEMsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDO0FBQUEsUUFDckIsQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLENBQUM7QUFBQSxRQUNqQyxDQUFDLFFBQVEsQ0FBVSxNQUFlLG1CQUFtQixDQUFDO0FBQUEsUUFDdEQsQ0FBQyxRQUFRLENBQVUsSUFBSSxDQUFDO0FBQUEsUUFDeEIsQ0FBQyxRQUFRLENBQVUsSUFBSSxDQUFDO0FBQUEsUUFDeEIsQ0FBQyxVQUFVLENBQUMsUUFBUSxxQkFBcUIsQ0FBQztBQUFBLFFBQzFDLENBQUMsUUFBUSxDQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFBQSxRQUNwQyxDQUFDLGlCQUFpQixDQUFDLGVBQWUsNEJBQTRCLENBQUM7QUFBQSxRQUMvRCxDQUFDLE9BQU8sQ0FBVSxHQUFHLENBQUM7QUFBQSxRQUN0QixDQUFDLFFBQVEsQ0FBVSxJQUFJLENBQUM7QUFBQSxRQUN4QixDQUFDLFVBQVUsQ0FBQyxRQUFRLHFCQUFxQixDQUFDO0FBQUEsUUFDMUMsQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLDJCQUEyQixDQUFDO0FBQUEsUUFDNUQsQ0FBQyxvQkFBb0IsQ0FBQyxrQkFBa0IsK0JBQStCLENBQUM7QUFBQSxRQUN4RSxDQUFDLE9BQU8sQ0FBVyxHQUFHLENBQUM7QUFBQSxRQUN2QixDQUFDLFVBQVUsQ0FBQyxRQUFRLHFCQUFxQixDQUFDO0FBQUEsUUFDMUMsQ0FBQyxPQUFPLENBQVUsS0FBYyxvQkFBb0IsQ0FBQztBQUFBLFFBQ3JELENBQUMsU0FBUyxDQUFXLEtBQUssQ0FBQztBQUFBLFFBQzNCLENBQUMsT0FBTyxDQUFVLEdBQUcsQ0FBQztBQUFBLFFBQ3RCLENBQUMsT0FBTyxDQUFVLEdBQUcsQ0FBQztBQUFBLFFBQ3RCLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQztBQUFBLFFBQ25CLENBQUMsWUFBWSxDQUFDQyxTQUFRLENBQUM7QUFBQSxRQUN2QixDQUFDLFNBQVMsQ0FBVSxLQUFLLENBQUM7QUFBQSxRQUMxQixDQUFDLGFBQWEsQ0FBQyxNQUFNLG1CQUFtQixDQUFDO0FBQUEsUUFDekMsQ0FBQyxVQUFVLENBQUMsUUFBUSxxQkFBcUIsQ0FBQztBQUFBLFFBQzFDLENBQUMsa0JBQWtCLENBQUMsZ0JBQWdCLDZCQUE2QixDQUFDO0FBQUEsUUFDbEUsQ0FBQyx3QkFBd0IsQ0FBQyxzQkFBc0IsbUNBQW1DLENBQUM7QUFBQSxRQUNwRixDQUFDLFlBQVksQ0FBQyxVQUFVLHVCQUF1QixDQUFDO0FBQUEsUUFDaEQsQ0FBQyxRQUFRLENBQVUsSUFBSSxDQUFDO0FBQUEsUUFDeEIsQ0FBQyxRQUFRLENBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUFBLFFBQ3BDLENBQUMscUJBQXFCLENBQU0sbUJBQXdCLGdDQUFnQyxDQUFDO0FBQUEsUUFDckYsQ0FBQyxpQkFBaUIsQ0FBTSxlQUFvQiw0QkFBNEIsQ0FBQztBQUFBLFFBQ3pFLENBQUMsV0FBVyxDQUFXLE9BQU8sQ0FBQztBQUFBLFFBQy9CLENBQUMsa0JBQWtCLENBQVcsY0FBYyxDQUFDO0FBQUEsUUFDN0MsQ0FBQyxjQUFjLENBQUMsWUFBWSx5QkFBeUIsQ0FBQztBQUFBLFFBQ3RELENBQUMsdUJBQXVCLENBQUMsbUJBQW1CLENBQUM7QUFBQSxRQUM3QyxDQUFDLGVBQWUsQ0FBVSxhQUFzQiwwQkFBMEIsQ0FBQztBQUFBLFFBQzNFLENBQUMseUJBQXlCLENBQUMsWUFBWSxDQUFDO0FBQUEsUUFDeEMsQ0FBQyxzQkFBc0IsQ0FBQyxTQUFTLENBQUM7QUFBQSxRQUNsQyxDQUFDLGFBQWEsQ0FBVSxXQUFvQixvQkFBb0IsQ0FBQztBQUFBLFFBQ2pFLENBQUMsUUFBUSxDQUFXLElBQUksQ0FBQztBQUFBLFFBQ3pCLENBQUMsZUFBZSxDQUFXLFdBQVcsQ0FBQztBQUFBLFFBQ3ZDLENBQUMsT0FBTyxDQUFVLEdBQUcsQ0FBQztBQUFBLFFBQ3RCLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQztBQUFBLFFBQ25CLENBQUMsZUFBZSxDQUFDLGFBQWEsMEJBQTBCLENBQUM7QUFBQTtBQUFBLFFBRXpELENBQUMsV0FBVyxDQUFNLFNBQWMsc0JBQXNCLENBQUM7QUFBQSxRQUN2RCxDQUFDLE9BQU8sQ0FBVyxHQUFHLENBQUM7QUFBQSxRQUN2QixDQUFDLHNCQUFzQixDQUFDLG9CQUFvQixpQ0FBaUMsQ0FBQztBQUFBLFFBQzlFLENBQUMsT0FBTyxDQUFVLEdBQUcsQ0FBQztBQUFBLFFBQ3RCLENBQUMsT0FBTyxDQUFVLEdBQUcsQ0FBQztBQUFBLFFBQ3RCLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQztBQUFBLFFBQ2IsQ0FBQyxPQUFPLENBQVcsR0FBRyxDQUFDO0FBQUEsUUFDdkIsQ0FBQyxhQUFhLENBQVUsV0FBb0Isb0JBQW9CLENBQUM7QUFBQSxRQUNqRSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUM7QUFBQSxRQUNqQixDQUFDLGNBQWMsQ0FBVSxVQUFVLENBQUM7QUFBQSxRQUNwQyxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUM7QUFBQSxRQUN6QixDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUM7QUFBQSxRQUMzQixDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUM7QUFBQSxRQUN6QixDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUM7QUFBQSxRQUN6QixDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUM7QUFBQSxRQUMzQixDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUM7QUFBQSxRQUN2QixDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUM7QUFBQSxRQUN2QixDQUFDLGdCQUFnQixDQUFDLFlBQVksQ0FBQztBQUFBLFFBQy9CLENBQUMsbUJBQW1CLENBQUMsZUFBZSxDQUFDO0FBQUEsUUFDckMsQ0FBQyxtQkFBbUIsQ0FBQyxlQUFlLENBQUM7QUFBQSxRQUNyQyxDQUFDLFFBQVEsQ0FBVSxJQUFJLENBQUM7QUFBQSxRQUN4QixDQUFDLFVBQVUsQ0FBQyxRQUFRLHFCQUFxQixDQUFDO0FBQUEsUUFDMUMsQ0FBQyxtQkFBbUIsQ0FBQyxlQUFlLENBQUM7QUFBQSxRQUNyQyxDQUFDLGFBQWEsQ0FBQyxXQUFXLHdCQUF3QixDQUFDO0FBQUEsUUFDbkQsQ0FBQyxXQUFXLENBQVUsT0FBTyxDQUFDO0FBQUEsUUFDOUIsQ0FBQyxPQUFPLENBQVUsR0FBRyxDQUFDO0FBQUEsUUFDdEIsQ0FBQyxRQUFRLENBQVUsSUFBSSxDQUFDO0FBQUEsUUFDeEIsQ0FBQyxTQUFTLENBQUMsT0FBTyxvQkFBb0IsQ0FBQztBQUFBLFFBQ3ZDLENBQUMsMEJBQTBCLENBQUMsYUFBYSxDQUFDO0FBQUEsUUFDMUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxvQkFBb0IsQ0FBQztBQUFBLFFBQ3ZDLENBQUMsUUFBUSxDQUFVLElBQUksQ0FBQztBQUFBLFFBQ3hCLENBQUMsV0FBVyxDQUFDLFNBQVMsc0JBQXNCLENBQUM7QUFBQSxRQUM3QyxDQUFDLE9BQU8sQ0FBVyxHQUFHLENBQUM7QUFBQSxRQUN2QixDQUFDLE9BQU8sQ0FBVSxHQUFHLENBQUM7QUFBQSxRQUN0QixDQUFDLFFBQVEsQ0FBVSxJQUFJLENBQUM7QUFBQSxRQUN4QixDQUFDLG1CQUFtQixDQUFVLGlCQUEwQixvQkFBb0IsQ0FBQztBQUFBLFFBQzdFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztBQUFBLFFBQ2YsQ0FBQyxhQUFhLENBQUMsV0FBVyx3QkFBd0IsQ0FBQztBQUFBLFFBQ25ELENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQztBQUFBLE1BQ25CLENBQUM7QUFBQTtBQUFBOzs7QUNqS0QsTUFvQmE7QUFwQmI7QUFBQTtBQUFBO0FBR0E7QUFHQTtBQUVBO0FBWU8sTUFBTSxpQkFBTixNQUFxQjtBQUFBLFFBSTFCLFlBQW9CLFNBQXdCO0FBQXhCO0FBQ2xCLGVBQUssT0FBTyxvQkFBSSxJQUFJO0FBQ3BCLGVBQUssa0JBQWtCO0FBQUEsUUFDekI7QUFBQSxRQUNBLFlBQVksS0FBb0M7QUFDOUMsaUJBQU8sS0FBSyxLQUFLLElBQUksR0FBRztBQUFBLFFBQzFCO0FBQUEsUUFDQSxZQUFZLEtBQWMsVUFBMEI7QUFDbEQsZUFBSyxLQUFLLElBQUksS0FBSyxRQUFRO0FBQUEsUUFDN0I7QUFBQSxRQUNBLElBQ0UsZUFDQSxRQUNBLFNBQ0EsZUFDQSxzQkFDTTtBQUNOLDJCQUFpQixjQUFjLFlBQVksSUFBSTtBQUMvQyxnQkFBTSxTQUFTLEtBQUssUUFBUTtBQUM1QixnQkFBTSxxQkFBcUIsS0FBSyxRQUFRLHNCQUFzQjtBQUM5RCxlQUFLLFFBQVEsZUFBZSxLQUFLLFFBQVEsd0JBQXdCLENBQUM7QUFDbEUsZ0JBQU0sVUFBVSxDQUFDO0FBQ2pCLHFCQUFXLFNBQVMsUUFBUTtBQUMxQixvQkFBUSxLQUFLLEVBQUUsU0FBUyxRQUFRLFFBQVEsVUFBVSxFQUFFLFFBQVEsTUFBTSxPQUFPLEVBQUUsQ0FBQztBQUFBLFVBQzlFO0FBQ0EscUJBQVcsVUFBVSxTQUFTO0FBQzVCLG9CQUFRLEtBQUssRUFBRSxTQUFTLFFBQVEsUUFBUSxVQUFVLEVBQUUsUUFBUSxPQUFPLE9BQU8sRUFBRSxDQUFDO0FBQUEsVUFDL0U7QUFDQSxjQUFJLHNCQUFzQjtBQUN4QixvQkFBUSxLQUFLLEVBQUUsU0FBUyxRQUFRLFFBQVEsVUFBVSxxQkFBcUIsQ0FBQztBQUFBLFVBQzFFO0FBQ0EsZ0JBQU0sWUFBWSxPQUFPLGdCQUFnQjtBQUFBLFlBQ3ZDLFFBQVEsY0FBYyxnQkFBZ0IsbUJBQW1CLENBQUM7QUFBQSxZQUMxRDtBQUFBLFlBQ0EsT0FBTyxjQUFjLFlBQVk7QUFBQSxVQUNuQyxDQUFDO0FBRUQsY0FBSSxLQUFLLFFBQVEsa0JBQWtCLGFBQWE7QUFDOUMsa0JBQU0sY0FBYztBQUFBLGNBQ2xCLFVBQVUsS0FBSyxRQUFRO0FBQUEsY0FDdkIsaUJBQWlCLGNBQWM7QUFBQSxjQUMvQjtBQUFBLGNBQ0E7QUFBQSxZQUNGO0FBQ0Esa0JBQU0scUJBQXFCLEtBQUssUUFBUSxvQkFBb0IsSUFBSSxLQUFLLFFBQVEsZ0JBQWlCO0FBQzlGLCtCQUFvQixLQUFLLFdBQVc7QUFBQSxVQUN0QztBQUVBLDZCQUFtQixZQUFZLGNBQWMsZUFBZTtBQUM1RCw2QkFBbUIsYUFBYSxHQUFHLFNBQVM7QUFDNUMsNkJBQW1CLG1CQUFtQixHQUFHLGFBQWE7QUFDdEQsZUFBSyxRQUFRLGVBQWUsS0FBSyxRQUFRLHdCQUF3QixJQUFJLENBQUM7QUFDdEUsZUFBSyxRQUFRO0FBRWIsY0FDRSxLQUFLLFFBQVEseUJBQXlCLEtBQUssUUFBUSxxQkFDbkQsS0FBSyxRQUFRLGNBQWMsYUFDM0I7QUFDQSxpQkFBSyxRQUFRLGVBQWU7QUFBQSxVQUM5QjtBQUNBLGNBQUksS0FBSyxRQUFRLHlCQUF5QixLQUFLLFFBQVEsbUJBQW1CO0FBQ3hFLGlCQUFLLFFBQVEsTUFBTTtBQUFBLFVBQ3JCO0FBQ0EseUJBQWUsY0FBYyxZQUFZLElBQUk7QUFBQSxRQUMvQztBQUFBLFFBQ0EsVUFBZ0I7QUFBQSxRQUVoQjtBQUFBLFFBQ0EsTUFBTSxhQUEwQiw2QkFBaUU7QUFDL0YsMkJBQWlCLFlBQVksSUFBSTtBQUNqQyxnQkFBTSxTQUFTLEtBQUssUUFBUTtBQUM1QixnQkFBTSxtQkFBNkIsQ0FBQztBQUdwQyxnQkFBTSxpQkFBd0U7QUFBQSxZQUM1RSxFQUFFLFNBQVMsY0FBYyxXQUFXLE1BQU07QUFBQSxZQUMxQyxFQUFFLFNBQVMsYUFBK0IsV0FBVyxZQUFZO0FBQUEsVUFDbkU7QUFDQSx5QkFBZSxRQUFRLENBQUMsU0FBUztBQUMvQixnQkFBSSxPQUFPLFNBQVMsSUFBSSxLQUFLLE9BQU8sR0FBRztBQUNyQywrQkFBaUIsS0FBSyxVQUFVLEtBQUssU0FBUyxHQUFHO0FBQUEsWUFDbkQ7QUFBQSxVQUNGLENBQUM7QUFFRCxnQkFBTSxlQUFlLG1CQUFtQiw2QkFBNkIsS0FBSyxRQUFRLE9BQU8sTUFBTTtBQUMvRixnQkFBTSxXQUFXLFlBQVksZ0JBQWdCLFlBQVk7QUFDekQsZ0JBQU0sT0FBTyxHQUFHLGlCQUFpQixLQUFLLElBQUksQ0FBQztBQUFBLEVBQUssYUFBYSx5QkFBeUI7QUFBQSxFQUFLLFFBQVE7QUFDbkcsZ0JBQU0sZUFBZSxPQUFPLG1CQUFtQixFQUFFLE1BQU0sT0FBTyxZQUFZLEtBQUssQ0FBQztBQUNoRixvQkFBVSxXQUFXLE1BQU0sWUFBWSxZQUFZLElBQUksaUJBQWlCLElBQUksRUFBRTtBQUU5RSxnQkFBTSxrQkFBa0IsT0FBTyxzQkFBc0I7QUFBQSxZQUNuRCxTQUFTLEVBQUUsUUFBUSxjQUFjLFlBQVksT0FBTztBQUFBLFlBQ3BELFFBQVE7QUFBQSxZQUNSLE9BQU8sWUFBWTtBQUFBLFVBQ3JCLENBQUM7QUFFRCx5QkFBZSxZQUFZLElBQUk7QUFDL0IsaUJBQU8sRUFBRSxhQUFhLGlCQUFpQixzQkFBc0IsYUFBYSxjQUFjO0FBQUEsUUFDMUY7QUFBQSxRQUVBLDJCQUNFLGVBQzBCO0FBQzFCLGdCQUFNLElBQUksT0FBTyxrQkFBa0IsV0FBVyxnQkFBZ0IsY0FBYztBQUM1RSxnQkFBTSxJQUFJLE9BQU8sa0JBQWtCLFdBQVcsSUFBSSxjQUFjLEtBQUs7QUFDckUsZ0JBQU0sSUFBSSxPQUFPLGtCQUFrQixXQUFXLElBQUksY0FBYyxLQUFLO0FBQ3JFLGdCQUFNLG9CQUFvQixLQUFLLFFBQVEsT0FBTyxPQUFPO0FBQ3JELGNBQUksS0FBSyxxQkFBcUIsS0FBSyxxQkFBcUIsS0FBSyxtQkFBbUI7QUFDOUUsbUJBQU8sQ0FBQyxHQUFHLEdBQUcsQ0FBQztBQUFBLFVBQ2pCO0FBQ0EsZ0JBQU0sT0FBTyxJQUFJLElBQUk7QUFDckIsY0FBSSxrQkFBa0IsS0FBSyxLQUFLLEtBQUssS0FBSyxJQUFJLENBQUM7QUFDL0MsY0FBSSxrQkFBa0IsbUJBQW1CO0FBQ3ZDLDhCQUFrQixLQUFLLEtBQUssS0FBSyxLQUFLLElBQUksQ0FBQztBQUMzQyxnQkFBSSxrQkFBa0IsbUJBQW1CO0FBQ3ZDLG9CQUFNLElBQUksTUFBTSw2Q0FBNkM7QUFBQSxZQUMvRDtBQUNBLG1CQUFPLENBQUMsaUJBQWlCLGlCQUFpQixlQUFlO0FBQUEsVUFDM0QsT0FBTztBQUNMLG1CQUFPLENBQUMsaUJBQWlCLGlCQUFpQixDQUFDO0FBQUEsVUFDN0M7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQ2xKQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE1BNkNNLHdDQWlEQSx5QkFzQkEsaUJBd0JPO0FBNUliO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBa0NBLE1BQU0seUNBQXlDLENBQzdDLGNBQ0Esc0JBQ1c7QUFDWCxZQUFJLGtCQUFrQixXQUFXLGFBQWEsUUFBUTtBQUNwRCxnQkFBTSxJQUFJO0FBQUEsWUFDUiw0QkFBNEIsa0JBQWtCLE1BQU0sd0NBQ2xELGFBQWEsTUFDZjtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBRUEsY0FBTSxhQUF1QixDQUFDO0FBQzlCLGlCQUFTLElBQUksR0FBRyxJQUFJLGFBQWEsUUFBUSxFQUFFLEdBQUc7QUFDNUMsZ0JBQU0sT0FBTyxhQUFhLENBQUMsRUFBRTtBQUM3QixrQkFBUSxrQkFBa0IsQ0FBQyxHQUFHO0FBQUEsWUFDNUIsS0FBSyxRQUFRO0FBQ1gseUJBQVcsS0FBSyxFQUFFO0FBQ2xCO0FBQUEsWUFDRjtBQUFBLFlBQ0EsS0FBSyxRQUFRO0FBQ1gseUJBQVcsS0FBSyxHQUFHLElBQUksRUFBRTtBQUN6QjtBQUFBLFlBQ0Y7QUFBQSxZQUNBLEtBQUssUUFBUTtBQUNYLG9CQUFNLE9BQU8sYUFBYSxDQUFDLEVBQUUsS0FBSztBQUNsQyx5QkFBVyxLQUFLLEdBQUcsSUFBSSxJQUFJLElBQUksRUFBRTtBQUNqQztBQUFBLFlBQ0Y7QUFBQSxZQUNBLEtBQUssUUFBUTtBQUNYLG9CQUFNLE9BQU8sYUFBYSxDQUFDLEVBQUUsS0FBSyxLQUFLLEdBQUc7QUFDMUMseUJBQVcsS0FBSyxHQUFHLElBQUksSUFBSSxJQUFJLEVBQUU7QUFDakM7QUFBQSxZQUNGO0FBQUEsWUFDQTtBQUNFLG9CQUFNLElBQUksTUFBTSxpQ0FBaUMsa0JBQWtCLENBQUMsQ0FBQyxFQUFFO0FBQUEsVUFDM0U7QUFBQSxRQUNGO0FBRUEsZUFBTyxXQUFXLEtBQUssR0FBRztBQUFBLE1BQzVCO0FBU0EsTUFBTSwwQkFBMEIsQ0FDOUIsYUFDQSxjQUNBLHlCQUNXO0FBR1gsWUFBSSxNQUFNLFlBQVk7QUFDdEIsWUFBSSxZQUFZLGFBQWEsTUFBTTtBQUNqQyxpQkFBTyxNQUFNLFlBQVksWUFBWSxPQUFPO0FBQUEsUUFDOUM7QUFDQSxlQUNFLE1BQ0EsdUJBQ0EsSUFBSTtBQUFBLFVBQ0Y7QUFBQSxVQUNBLFlBQVksYUFBYSxxQkFDdkIsSUFBSSxNQUF3QyxhQUFhLE1BQU0sRUFBRSxLQUFLLE1BQU07QUFBQSxRQUNoRixDQUFDO0FBQ0gsZUFBTztBQUFBLE1BQ1Q7QUFFQSxNQUFNLGtCQUFOLE1BQTZDO0FBQUEsUUFJM0MsWUFBWSxhQUE2QjtBQUN2QyxjQUFJLGFBQWE7QUFDZixpQkFBSyxlQUFlLFlBQVk7QUFDaEMsaUJBQUssU0FBUyxZQUFZO0FBQUEsVUFDNUI7QUFBQSxRQUNGO0FBQUEsUUFFQSxlQUFlLGNBQXdDO0FBQ3JELGlCQUFPLEtBQUssaUJBQWlCO0FBQUEsUUFDL0I7QUFBQSxRQUVBLFNBQVMsUUFBNEI7QUFDbkMsaUJBQU8sS0FBSyxXQUFXO0FBQUEsUUFDekI7QUFBQSxNQUNGO0FBTU8sTUFBTSxnQkFBTixNQUFvQjtBQUFBLFFBQXBCO0FBa0JMO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxrQ0FBa0M7QUFPbEM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGlDQUFpQztBQWdDakMsZUFBUSxpQkFBMkM7QUFDbkQsZUFBUSxxQkFBbUQ7QUFDM0QsbUNBQW9CO0FBQ3BCLHVDQUF3QjtBQUd4QjtBQUFBLGVBQVEsaUJBQXNDLENBQUM7QUFFL0M7QUFBQSxlQUFRLGlCQUFzRCxvQkFBSSxJQUFJO0FBT3RFLCtCQUE4QjtBQUk5QjtBQUFBO0FBQUE7QUFBQSxxQ0FBa0Qsb0JBQUksSUFBSTtBQUsxRDtBQUFBO0FBQUE7QUFBQSxlQUFRLHlCQUEyRCxvQkFBSSxJQUFJO0FBSzNFO0FBQUE7QUFBQTtBQUFBLDRDQUE0RSxvQkFBSSxJQUFJO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxRQTdDcEYsSUFBSSwwQkFBc0Q7QUFDeEQsY0FBSSxLQUFLLG9CQUFvQixNQUFNO0FBQ2pDLGtCQUFNLElBQUksTUFBTSx5RUFBeUU7QUFBQSxVQUMzRjtBQUVBLGNBQUksT0FBTyxLQUFLLGlCQUFpQixJQUFJLEtBQUssZUFBZTtBQUN6RCxjQUFJLENBQUMsTUFBTTtBQUNULG1CQUFPLENBQUM7QUFDUixpQkFBSyxpQkFBaUIsSUFBSSxLQUFLLGlCQUFpQixJQUFJO0FBQUEsVUFDdEQ7QUFFQSxpQkFBTztBQUFBLFFBQ1Q7QUFBQSxRQW1DQSxNQUFNLFdBQVdDLE1BQVUsU0FBb0M7QUFDN0QsZUFBSyxNQUFNQTtBQUNYLGdCQUFNLG1CQUFxQyxDQUFDO0FBQzVDLGdCQUFNLG1CQUF3QztBQUFBLFlBQzVDLGdCQUFnQjtBQUFBLGNBQ2QsZ0NBQWdDLFFBQVEsT0FBTztBQUFBLGNBQy9DLGtDQUFrQyxRQUFRLE9BQU87QUFBQSxjQUNqRCw2QkFBNkIsUUFBUSxPQUFPO0FBQUEsY0FDNUMsZUFBZSxRQUFRLE9BQU87QUFBQSxjQUM5QixtQ0FBbUMsUUFBUSxPQUFPO0FBQUEsY0FDbEQsMEJBQTBCLFFBQVEsT0FBTztBQUFBLGNBQ3pDLDBCQUEwQixRQUFRLE9BQU87QUFBQSxjQUN6QywwQkFBMEIsUUFBUSxPQUFPO0FBQUEsWUFDM0M7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUdBLGdCQUFNLDRCQUE0QixDQUFDLFlBQ2pDLFFBQVEsU0FBUyxJQUFJLE9BQU8sS0FBSyxpQkFBaUIsS0FBSyxPQUFPLEtBQUs7QUFFckUsY0FBSSxDQUFDLDBCQUEwQixxREFBdUUsR0FBRztBQUN2RyxzQ0FBMEIsaUJBQWlCO0FBQUEsVUFDN0M7QUFDQSxvQ0FBMEIsWUFBWTtBQUV0QyxvQ0FBMEIsV0FBNkI7QUFFdkQsZUFBSyxTQUFTLE1BQU0sUUFBUSxjQUFjLGdCQUFnQjtBQUMxRCxlQUFLLGNBQWMsSUFBSSxnQkFBZ0IsUUFBUSxRQUFTLE1BQU0sUUFBUSxtQkFBbUIsQ0FBRTtBQUMzRixlQUFLLGlCQUFpQixxQkFBcUIsSUFBSTtBQUMvQyxlQUFLLGlCQUFpQixJQUFJLGVBQWUsSUFBSTtBQUM3QyxlQUFLLFVBQVUsb0JBQUksSUFBSTtBQUN2QixlQUFLLHVCQUF1QixvQkFBSSxJQUFJO0FBQ3BDLGVBQUssbUJBQW1CLG9CQUFJLElBQUk7QUFHaEMsMEJBQWdCQSxLQUFJLFVBQVcsQ0FBQyxDQUFDQSxLQUFJLEtBQUs7QUFJMUMsZUFBSyxPQUFPLG9CQUFvQixDQUFDLE9BQU87QUFDdEMsZ0JBQUksR0FBRyxpQkFBaUIsb0JBQW9CO0FBRTFDLHNCQUFRLE1BQU0sbURBQW1ELEdBQUcsTUFBTSxPQUFPLEVBQUU7QUFBQSxZQUNyRjtBQUFBLFVBQ0Y7QUFFQSxpQkFBTyxlQUFlLEtBQUssSUFBSSxRQUFRLFVBQVU7QUFBQSxZQUMvQyxPQUFPLEtBQUs7QUFBQSxZQUNaLFVBQVU7QUFBQSxZQUNWLFlBQVk7QUFBQSxZQUNaLGNBQWM7QUFBQSxVQUNoQixDQUFDO0FBQ0QsaUJBQU8sZUFBZSxLQUFLLElBQUksUUFBUSxXQUFXO0FBQUEsWUFDaEQsT0FBTztBQUFBLFlBQ1AsVUFBVTtBQUFBLFlBQ1YsWUFBWTtBQUFBLFlBQ1osY0FBYztBQUFBLFVBQ2hCLENBQUM7QUFHRCxlQUFLLGFBQWE7QUFBQSxRQUNwQjtBQUFBLFFBRUEsVUFBZ0I7QUFDZCxjQUFJLE9BQU8sS0FBSyxhQUFhLGFBQWE7QUFDeEMsaUJBQUssU0FBUyxRQUFRO0FBQUEsVUFDeEI7QUFDQSxlQUFLLGVBQWUsUUFBUTtBQUFBLFFBQzlCO0FBQUEsUUFFQSxvQkFBdUM7QUFDckMsY0FBSSxDQUFDLEtBQUssZ0JBQWdCO0FBQ3hCLGlCQUFLLGlCQUFpQixLQUFLLE9BQU8scUJBQXFCO0FBQUEsVUFDekQ7QUFDQSxpQkFBTyxLQUFLO0FBQUEsUUFDZDtBQUFBLFFBRUEsd0JBQStDO0FBQzdDLGNBQUksQ0FBQyxLQUFLLG9CQUFvQjtBQUM1QixrQkFBTSxpQkFBaUIsS0FBSyxrQkFBa0I7QUFDOUMsa0JBQU0sd0JBQWtELENBQUM7QUFFekQsZ0JBQUksS0FBSyxjQUFjLGFBQWE7QUFDbEMsb0NBQXNCLGtCQUFrQjtBQUFBLGdCQUN0QyxVQUFVLEtBQUs7QUFBQSxnQkFDZiwyQkFBMkIsS0FBSyx3QkFBd0I7QUFBQSxnQkFDeEQscUJBQXFCLEtBQUssd0JBQXdCLElBQUk7QUFBQSxjQUN4RDtBQUFBLFlBQ0Y7QUFFQSxpQkFBSyxxQkFBcUIsZUFBZSxpQkFBaUIscUJBQXFCO0FBQUEsVUFDakY7QUFDQSxpQkFBTyxLQUFLO0FBQUEsUUFDZDtBQUFBLFFBRUEsaUJBQXVCO0FBQ3JCLGNBQUksS0FBSyxvQkFBb0I7QUFDM0IsaUJBQUssbUJBQW1CLElBQUk7QUFDNUIsaUJBQUsscUJBQXFCO0FBQUEsVUFDNUI7QUFBQSxRQUNGO0FBQUEsUUFFQSxRQUFjO0FBQ1osY0FBSSxDQUFDLEtBQUssZ0JBQWdCO0FBQ3hCO0FBQUEsVUFDRjtBQUVBLDJCQUFpQjtBQUVqQixlQUFLLGVBQWU7QUFDcEIsY0FBSTtBQUNKLGNBQUksS0FBSyxjQUFjLFFBQVE7QUFDN0IsaUJBQUssZUFBZTtBQUFBLGNBQ2xCLEtBQUs7QUFBQSxjQUNMO0FBQUEsY0FDQSxLQUFLLHdCQUF3QjtBQUFBLGNBQzdCLEtBQUs7QUFBQSxjQUNMO0FBQUEsWUFDRjtBQUVBLDhCQUFrQixLQUFLLE9BQU87QUFBQTtBQUFBLGNBRTVCLEVBQUUsTUFBTSxLQUFLLHdCQUF3QixJQUFJLEdBQUcsT0FBTyxlQUFlLFdBQVcsZUFBZSxTQUFTO0FBQUEsWUFDdkc7QUFFQSxpQkFBSyxlQUFlLElBQUksaUJBQWlCLEtBQUssY0FBYztBQUM1RCxpQkFBSyxpQkFBaUIsQ0FBQztBQUN2QixpQkFBSyxlQUFlO0FBQUEsY0FDbEIsS0FBSztBQUFBLGNBQ0w7QUFBQSxjQUNBO0FBQUEsY0FDQTtBQUFBLGNBQ0EsS0FBSyx3QkFBd0IsSUFBSTtBQUFBLFlBQ25DO0FBQUEsVUFDRjtBQUVBLGVBQUssT0FBTyxNQUFNLE9BQU8sQ0FBQyxLQUFLLGVBQWUsT0FBTyxDQUFDLENBQUM7QUFDdkQsZUFBSyxlQUFlLHNCQUFzQjtBQUMxQyxlQUFLLGlCQUFpQjtBQUN0QixlQUFLLHdCQUF3QjtBQUU3QixjQUFJLEtBQUssY0FBYyxRQUFRO0FBQzdCLGlCQUFLLGdCQUFpQixTQUFTLFdBQVcsSUFBSSxFQUFFLEtBQUssTUFBTTtBQUN6RCxvQkFBTSxhQUFhLElBQUksZUFBZSxnQkFBZ0IsZUFBZSxDQUFDO0FBQ3RFLG9CQUFNLGlCQUFpQixLQUFLLGVBQWUsSUFBSSxlQUFlO0FBQzlELHVCQUFTLElBQUksR0FBRyxJQUFJLFdBQVcsU0FBUyxHQUFHLEtBQUs7QUFDOUMsc0JBQU0sb0JBQW9CLGVBQWUsQ0FBQztBQUMxQyxzQkFBTSxXQUFXLGtCQUFrQjtBQUNuQyxzQkFBTSxhQUFhLEtBQUssUUFBUSxJQUFJLFFBQVE7QUFDNUMsc0JBQU0sYUFBYSxXQUFXO0FBQzlCLHNCQUFNLGFBQWEsV0FBVztBQUM5QixzQkFBTSxjQUFjLGtCQUFrQjtBQUN0QyxzQkFBTSxtQkFBbUIsa0JBQWtCO0FBQzNDLHNCQUFNLG9CQUFvQixrQkFBa0I7QUFDNUMsc0JBQU0sZUFBZSxXQUFXLElBQUksQ0FBQztBQUNyQyxzQkFBTSxhQUFhLFdBQVcsSUFBSSxJQUFJLENBQUM7QUFFdkMsb0JBQUksT0FBTyxLQUFLLGtCQUFrQixhQUFhO0FBQzdDLHVCQUFLLGdCQUFnQjtBQUFBLGdCQUN2QjtBQUVBLHNCQUFNLFlBQVksT0FBTyxlQUFlLEtBQUssYUFBYTtBQUMxRCxzQkFBTSxVQUFVLE9BQU8sYUFBYSxLQUFLLGFBQWE7QUFFdEQsb0JBQUksQ0FBQyxPQUFPLGNBQWMsU0FBUyxLQUFLLENBQUMsT0FBTyxjQUFjLE9BQU8sR0FBRztBQUN0RSx3QkFBTSxJQUFJLFdBQVcsMkJBQTJCO0FBQUEsZ0JBQ2xEO0FBRUEsb0JBQUksS0FBSyxJQUFJLE9BQU8sV0FBVyxRQUFRO0FBQ3JDLHVCQUFLLElBQUksT0FBTyxVQUFVLE9BQU87QUFBQSxvQkFDL0IsU0FBUztBQUFBLG9CQUNULGdCQUFnQixpQkFBaUIsSUFBSSxDQUFDLFdBQVc7QUFBQSxzQkFDL0MsTUFBTSxNQUFNO0FBQUEsc0JBQ1osVUFBVSwyQkFBMkIsTUFBTSxRQUFRO0FBQUEsb0JBQ3JELEVBQUU7QUFBQSxvQkFDRixpQkFBaUIsa0JBQWtCLElBQUksQ0FBQyxXQUFXO0FBQUEsc0JBQ2pELE1BQU0sTUFBTTtBQUFBLHNCQUNaLFVBQVUsMkJBQTJCLE1BQU0sUUFBUTtBQUFBLG9CQUNyRCxFQUFFO0FBQUEsb0JBQ0Y7QUFBQSxvQkFDQTtBQUFBLG9CQUNBO0FBQUEsb0JBQ0E7QUFBQSxvQkFDQTtBQUFBLG9CQUNBO0FBQUEsa0JBQ0YsQ0FBQztBQUFBLGdCQUNILE9BQU87QUFFTCxzQkFBSSxjQUFjO0FBQ2xCLG1DQUFpQixRQUFRLENBQUMsT0FBT0MsT0FBTTtBQUNyQyxtQ0FBZSxTQUFTQSxFQUFDLE9BQU8sTUFBTSxJQUFJLE9BQU8sMkJBQTJCLE1BQU0sUUFBUSxDQUFDO0FBQUEsa0JBQzdGLENBQUM7QUFDRCxzQkFBSSxlQUFlO0FBQ25CLG9DQUFrQixRQUFRLENBQUMsT0FBT0EsT0FBTTtBQUN0QyxvQ0FBZ0IsVUFBVUEsRUFBQyxPQUFPLE1BQU0sSUFBSSxPQUFPLDJCQUEyQixNQUFNLFFBQVEsQ0FBQztBQUFBLGtCQUMvRixDQUFDO0FBRUQsMEJBQVE7QUFBQSxvQkFDTix1QkFBdUIsUUFBUSxJQUFJLFVBQVUsSUFBSSxVQUFVLElBQUksV0FBVyxLQUFLLFdBQVcsR0FDeEYsWUFDRixtQkFBbUIsVUFBVSxTQUFTO0FBQUEsa0JBQ3hDO0FBQUEsZ0JBQ0Y7QUFDQSxzQkFBTSxPQUFPLEdBQUcsV0FBVyxLQUFLLFlBQVksS0FBSyxVQUFVLEVBQUU7QUFBQSxjQUMvRDtBQUNBLDhCQUFnQixNQUFNO0FBQ3RCLG1CQUFLLGVBQWUsT0FBTyxlQUFlO0FBQUEsWUFDNUMsQ0FBQztBQUFBLFVBQ0g7QUFDQSx5QkFBZTtBQUFBLFFBQ2pCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFFBYUEsSUFDRSxTQUNBLGtCQUNBLGVBQ0Esb0JBQ0EsMEJBQ0EsYUFDYztBQUNkLDJCQUFpQixRQUFRLElBQUk7QUFFN0IsZ0JBQU0sYUFBd0IsQ0FBQztBQUMvQixtQkFBUyxJQUFJLEdBQUcsSUFBSSxpQkFBaUIsUUFBUSxFQUFFLEdBQUc7QUFDaEQsa0JBQU0sT0FBTyxpQkFBaUIsQ0FBQyxFQUFFO0FBRWpDLGdCQUFJLFNBQVMsR0FBRztBQUNkO0FBQUEsWUFDRjtBQUNBLGtCQUFNLFVBQVUsS0FBSyxlQUFlLElBQUksSUFBSTtBQUM1QyxnQkFBSSxDQUFDLFNBQVM7QUFDWixvQkFBTSxJQUFJLE1BQU0sMEJBQTBCLElBQUksRUFBRTtBQUFBLFlBQ2xEO0FBQ0EsdUJBQVcsS0FBSyxPQUFPO0FBQUEsVUFDekI7QUFFQSxnQkFBTSxFQUFFLFNBQVMsZUFBZSxnQkFBZ0IsSUFBSSxRQUFRLFdBQVcsZ0JBQWdCO0FBR3ZGLGdCQUFNLHlCQUF5QixjQUFjLFdBQVcsSUFBSSxRQUFRLElBQUksQ0FBQyxHQUFHLE1BQU0sQ0FBQyxJQUFJO0FBQ3ZGLGNBQUksdUJBQXVCLFdBQVcsUUFBUSxRQUFRO0FBQ3BELGtCQUFNLElBQUksTUFBTSxlQUFlLHVCQUF1QixNQUFNLHFCQUFxQixRQUFRLE1BQU0sR0FBRztBQUFBLFVBQ3BHO0FBR0EsZ0JBQU0sb0JBQWtDLENBQUM7QUFDekMsZ0JBQU0sY0FBeUIsQ0FBQztBQUNoQyxtQkFBUyxJQUFJLEdBQUcsSUFBSSxRQUFRLFFBQVEsRUFBRSxHQUFHO0FBSXZDLGdCQUNFLENBQUMsT0FBTyxVQUFVLHVCQUF1QixDQUFDLENBQUMsS0FDM0MsdUJBQXVCLENBQUMsSUFBSSxNQUM1Qix1QkFBdUIsQ0FBQyxLQUFLLGFBQzdCO0FBQ0Esb0JBQU0sSUFBSSxNQUFNLHlCQUF5Qix1QkFBdUIsQ0FBQyxDQUFDLEVBQUU7QUFBQSxZQUN0RTtBQUNBLGdCQUFJLHVCQUF1QixDQUFDLE1BQU0sSUFBSTtBQUNwQztBQUFBLFlBQ0Y7QUFDQSxrQkFBTSxjQUFjLHVCQUF1QixDQUFDLE1BQU07QUFDbEQsa0JBQU0sZUFBZSx1QkFBdUIsQ0FBQyxNQUFNO0FBQ25ELGtCQUFNLGFBQ0osZUFBZSxlQUNYLHlCQUF5QixRQUFRLENBQUMsRUFBRSxVQUFVLFFBQVEsQ0FBQyxFQUFFLElBQUksSUFDN0QsbUJBQW1CLHVCQUF1QixDQUFDLEdBQUcsUUFBUSxDQUFDLEVBQUUsVUFBVSxRQUFRLENBQUMsRUFBRSxJQUFJO0FBQ3hGLDhCQUFrQixLQUFLLFVBQVU7QUFFakMsZ0JBQUksV0FBVyxTQUFTLEdBQUc7QUFDekI7QUFBQSxZQUNGO0FBQ0Esa0JBQU0sVUFBVSxLQUFLLGVBQWUsSUFBSSxXQUFXLElBQUk7QUFDdkQsZ0JBQUksQ0FBQyxTQUFTO0FBQ1osb0JBQU0sSUFBSSxNQUFNLDJCQUEyQixXQUFXLElBQUksRUFBRTtBQUFBLFlBQzlEO0FBQ0EsZ0JBQUksYUFBYTtBQUNmLG1CQUFLLGNBQWMsS0FBSyxPQUFPO0FBQUEsWUFDakM7QUFDQSxnQkFBSSxjQUFjO0FBQ2hCLGtCQUFJLGlCQUFpQixLQUFLLHFCQUFxQixJQUFJLEtBQUssZUFBZ0I7QUFDeEUsa0JBQUksQ0FBQyxnQkFBZ0I7QUFDbkIsaUNBQWlCLENBQUM7QUFDbEIscUJBQUsscUJBQXFCLElBQUksS0FBSyxpQkFBa0IsY0FBYztBQUFBLGNBQ3JFO0FBQ0EsNkJBQWUsS0FBSyxPQUFPO0FBQUEsWUFDN0I7QUFDQSx3QkFBWSxLQUFLLE9BQU87QUFBQSxVQUMxQjtBQUlBLGNBQUksV0FBVyxXQUFXLGlCQUFpQixVQUFVLFlBQVksV0FBVyxrQkFBa0IsUUFBUTtBQUVwRyxnQkFBSSxZQUFZLFdBQVcsR0FBRztBQUM1Qiw2QkFBZSxRQUFRLElBQUk7QUFDM0IscUJBQU87QUFBQSxZQUNUO0FBS0Esa0JBQU0sSUFBSTtBQUFBLGNBQ1IsV0FBVyxRQUFRLElBQUk7QUFBQSxZQUN6QjtBQUFBLFVBQ0Y7QUFLQSxjQUFJO0FBQ0osY0FBSSxpQkFBaUI7QUFDbkIsZ0JBQUksZ0JBQWdCO0FBQ3BCLGtCQUFNLFVBQW9CLENBQUM7QUFFM0IsNEJBQWdCLFFBQVEsQ0FBQyxNQUFNO0FBQzdCLG9CQUFNLE9BQU8sT0FBTyxFQUFFLFNBQVMsV0FBVyxDQUFDLEVBQUUsSUFBSSxJQUFJLEVBQUU7QUFDdkQsa0JBQUksS0FBSyxXQUFXLEdBQUc7QUFDckI7QUFBQSxjQUNGO0FBRUEsb0JBQU0sZ0JBQWdCLEVBQUUsNEJBQTRCLElBQUk7QUFDeEQsa0JBQUk7QUFDSixrQkFBSTtBQUNKLGtCQUFJLEVBQUUsMkJBQTJCO0FBQy9CLGdDQUFnQixLQUFLLFNBQVMsSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLElBQUksS0FBSyxTQUFTO0FBQzNFLGlDQUFpQixLQUFLLFNBQVMsSUFBSSxLQUFLLGdCQUFnQixLQUFLO0FBQUEsY0FDL0QsT0FBTztBQUNMLGdDQUFnQixLQUFLLFVBQVUsSUFBSSxLQUFLLFNBQVMsZ0JBQWdCO0FBQ2pFLGlDQUFpQjtBQUFBLGNBQ25CO0FBQ0EsOEJBQWdCLEtBQUssS0FBSyxnQkFBZ0IsYUFBYSxJQUFJO0FBQzNELHNCQUFRLEtBQUssYUFBYTtBQU0xQixvQkFBTSxxQkFBcUIsRUFBRSw0QkFBNEIsSUFBSTtBQUM3RCwrQkFDRSxLQUFLLFNBQVMsSUFBSSxLQUFLLEtBQUssS0FBSyxTQUFTLGtCQUFrQixJQUFJLGlCQUFpQixLQUFLLFNBQVM7QUFBQSxZQUNuRyxDQUFDO0FBSUQsa0JBQU0sc0JBQXNCO0FBQzVCLDRCQUFnQixLQUFLLEtBQUssZ0JBQWdCLG1CQUFtQixJQUFJO0FBQ2pFLGtCQUFNLGNBQWMsSUFBSSxZQUFZLGFBQWE7QUFDakQsNEJBQWdCLFFBQVEsQ0FBQyxHQUFHLE1BQU07QUFDaEMsb0JBQU0sU0FBUyxRQUFRLENBQUM7QUFDeEIsb0JBQU0sT0FBTyxPQUFPLEVBQUUsU0FBUyxXQUFXLENBQUMsRUFBRSxJQUFJLElBQUksRUFBRTtBQUN2RCxrQkFBSSxFQUFFLHdCQUF5QjtBQUM3QixvQkFBSSxXQUFXLGFBQWEsUUFBUSxLQUFLLE1BQU0sRUFBRSxJQUFJLElBQUk7QUFBQSxjQUMzRCxXQUFXLEVBQUUsMEJBQTBCO0FBQ3JDLG9CQUFJLFlBQVksYUFBYSxRQUFRLEtBQUssTUFBTSxFQUFFLElBQUksSUFBSTtBQUFBLGNBQzVELFdBQVcsRUFBRSwyQkFBMkI7QUFDdEMsb0JBQUksWUFBWSxhQUFhLFFBQVEsS0FBSyxNQUFNLEVBQUUsSUFBSSxJQUFJO0FBQUEsY0FDNUQsV0FBVyxFQUFFLHdCQUF5QjtBQUNwQyxvQkFBSSxhQUFhLGFBQWEsUUFBUSxLQUFLLE1BQU0sRUFBRSxJQUFJLElBQUk7QUFBQSxjQUM3RCxPQUFPO0FBQ0wsc0JBQU0sSUFBSSxNQUFNLDZCQUE2QiwyQkFBMkIsRUFBRSxJQUFJLENBQUMsRUFBRTtBQUFBLGNBQ25GO0FBQUEsWUFDRixDQUFDO0FBRUQsa0JBQU07QUFBQTtBQUFBLGNBRUosS0FBSyxlQUFlLE9BQU8sZUFBZSxlQUFlLFdBQVcsZUFBZSxPQUFPO0FBQUE7QUFDNUYsaUJBQUssT0FBTyxNQUFNLFlBQVksa0JBQWtCLFFBQVEsR0FBRyxhQUFhLEdBQUcsYUFBYTtBQUN4RixpQkFBSyxlQUFlLFFBQVEsa0JBQWtCLEVBQUU7QUFDaEQsbUNBQXVCLEVBQUUsUUFBUSxHQUFHLE1BQU0sZUFBZSxRQUFRLGtCQUFrQixPQUFPO0FBQUEsVUFDNUY7QUFFQSxnQkFBTSwwQkFBMEIsS0FBSyxlQUFlLDJCQUEyQixhQUFhO0FBQzVGLGdCQUFNLHVCQUF1Qix3QkFBd0IsQ0FBQyxNQUFNLEtBQUssd0JBQXdCLENBQUMsTUFBTTtBQUVoRyxnQkFBTSxNQUFNLHdCQUF3QixTQUFTLGtCQUFrQixvQkFBb0I7QUFDbkYsY0FBSSxXQUFXLEtBQUssZUFBZSxZQUFZLEdBQUc7QUFDbEQsY0FBSSxDQUFDLFVBQVU7QUFDYix1QkFBVyxLQUFLLGVBQWUsTUFBTSxTQUFTLHVCQUF1QjtBQUNyRSxpQkFBSyxlQUFlLFlBQVksS0FBSyxRQUFRO0FBQzdDLHNCQUFVLFFBQVEsTUFBTSxtQkFBbUIsR0FBRyxrQkFBa0IsUUFBUSxJQUFJLEVBQUU7QUFBQSxVQUNoRjtBQUdBLGNBQUksbUJBQW1CLFNBQVMsc0JBQXNCO0FBQ3BELGdCQUFJLGdCQUFnQixXQUFXLFNBQVMscUJBQXFCLFFBQVE7QUFDbkUsb0JBQU0sSUFBSTtBQUFBLGdCQUNSLDRDQUE0QyxTQUFTLHFCQUFxQixNQUFNLFNBQzlFLGdCQUFnQixNQUNsQixnQkFBZ0IsU0FBUyxZQUFZLElBQUk7QUFBQSxjQUMzQztBQUFBLFlBQ0Y7QUFDQSxxQkFBUyxJQUFJLEdBQUcsSUFBSSxnQkFBZ0IsUUFBUSxLQUFLO0FBQy9DLG9CQUFNLFVBQVUsZ0JBQWdCLENBQUM7QUFDakMsb0JBQU0sYUFBYSxRQUFRO0FBQzNCLG9CQUFNLGVBQWUsT0FBTyxRQUFRLFNBQVMsV0FBVyxJQUFJLFFBQVEsS0FBSztBQUN6RSxvQkFBTSxDQUFDLE1BQU0sTUFBTSxJQUFJLFNBQVMscUJBQXFCLENBQUM7QUFDdEQsa0JBQUksZUFBZSxRQUFRLGlCQUFpQixRQUFRO0FBQ2xELHNCQUFNLElBQUk7QUFBQSxrQkFDUixvQkFBb0IsQ0FBQywwQkFBMEIsSUFBSSxjQUFjLE1BQU0sY0FDckUsVUFDRixjQUFjLFlBQVksZ0JBQWdCLFNBQVMsWUFBWSxJQUFJO0FBQUEsZ0JBQ3JFO0FBQUEsY0FDRjtBQUFBLFlBQ0Y7QUFBQSxVQUNGO0FBRUE7QUFBQSxZQUNFO0FBQUEsWUFDQSxNQUNFLHlCQUF5QixRQUFRLElBQUksVUFBVSxHQUFHLFVBQVUsd0JBQXdCLENBQUMsQ0FBQyxJQUNwRix3QkFBd0IsQ0FBQyxDQUMzQixJQUFJLHdCQUF3QixDQUFDLENBQUM7QUFBQSxVQUNsQztBQUVBLGNBQUksS0FBSyxjQUFjLFVBQVUsS0FBSyxrQkFBa0IsYUFBYTtBQUNuRSxrQkFBTSxvQkFBdUM7QUFBQSxjQUMzQyxVQUFVLEtBQUs7QUFBQSxjQUNmLGFBQWEsU0FBUyxZQUFZO0FBQUEsY0FDbEM7QUFBQSxjQUNBO0FBQUEsWUFDRjtBQUNBLGlCQUFLLGVBQWUsS0FBSyxpQkFBaUI7QUFFMUMsZ0JBQUksS0FBSyxrQkFBa0IsYUFBYTtBQUN0QyxvQkFBTSx3QkFBd0IsS0FBSyx1QkFBdUIsSUFBSSxLQUFLLGdCQUFpQjtBQUNwRixvQ0FBdUIsS0FBSyxpQkFBaUI7QUFBQSxZQUMvQztBQUFBLFVBQ0Y7QUFFQSxlQUFLLGVBQWUsSUFBSSxVQUFVLFlBQVksYUFBYSx5QkFBeUIsb0JBQW9CO0FBRXhHLHlCQUFlLFFBQVEsSUFBSTtBQUMzQixpQkFBTztBQUFBLFFBQ1Q7QUFBQSxRQUVBLE9BQU8sV0FBbUIsTUFBd0I7QUFDaEQsZUFBSyxlQUFlLE9BQU8sV0FBVyxJQUFJO0FBQUEsUUFDNUM7QUFBQSxRQUVBLE9BQU8sS0FBYSxLQUFtQjtBQUNyQyxlQUFLLGVBQWUsT0FBTyxLQUFLLEdBQUc7QUFBQSxRQUNyQztBQUFBLFFBRUEsTUFBTSxTQUFTLFdBQW1CLGlCQUFrRDtBQUdsRixnQkFBTSxLQUFLLGVBQWUsU0FBUyxXQUFXLGVBQWU7QUFBQSxRQUMvRDtBQUFBLFFBRUEsTUFBTSxNQUFzQjtBQUMxQixpQkFBTyxLQUFLLGVBQWUsT0FBTyxJQUFJLEVBQUU7QUFBQSxRQUMxQztBQUFBLFFBRUEsS0FBSyxLQUFxQjtBQUN4QixpQkFBTyxLQUFLLGVBQWUsUUFBUSxHQUFHO0FBQUEsUUFDeEM7QUFBQSxRQUVBLGFBQWEsWUFBb0IsVUFBa0IsV0FBb0IsWUFBMEI7QUFDL0YsZ0JBQU0sS0FBSyx3QkFBd0IsSUFBSSxVQUFVO0FBQ2pELGNBQUksQ0FBQyxJQUFJO0FBQ1Asa0JBQU0sSUFBSSxNQUFNLDJCQUEyQixVQUFVLEVBQUU7QUFBQSxVQUN6RDtBQUVBLGdCQUFNLGFBQXlCO0FBQUEsWUFDN0I7QUFBQSxZQUNBO0FBQUEsWUFDQSxhQUFhLEdBQUcsQ0FBQztBQUFBLFlBQ2pCLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxTQUFTO0FBQUEsVUFDL0I7QUFDQSxlQUFLLFFBQVEsSUFBSSxVQUFVLFVBQVU7QUFBQSxRQUN2QztBQUFBLFFBRUEsY0FBYyxVQUF3QjtBQUNwQyxnQkFBTSxpQkFBaUIsS0FBSyxxQkFBcUIsSUFBSSxRQUFRO0FBQzdELGNBQUksZ0JBQWdCO0FBQ2xCLHVCQUFXLFFBQVEsZ0JBQWdCO0FBQ2pDLG1CQUFLLGVBQWUsUUFBUSxLQUFLLEVBQUU7QUFBQSxZQUNyQztBQUNBLGlCQUFLLHFCQUFxQixPQUFPLFFBQVE7QUFBQSxVQUMzQztBQUVBLGVBQUssaUJBQWlCLE9BQU8sUUFBUTtBQUNyQyxlQUFLLFFBQVEsT0FBTyxRQUFRO0FBQUEsUUFDOUI7QUFBQSxRQUVBLGNBQWMsVUFBa0IsU0FBeUIsUUFBK0M7QUFDdEcsZ0JBQU0sU0FBUyxLQUFLLFFBQVEsSUFBSSxRQUFRO0FBQ3hDLGNBQUksQ0FBQyxRQUFRO0FBQ1gsa0JBQU0sSUFBSSxNQUFNLHVCQUF1QixRQUFRLEVBQUU7QUFBQSxVQUNuRDtBQUNBLGdCQUFNLGFBQWEsT0FBTztBQUMxQixnQkFBTSxhQUFhLE9BQU87QUFDMUIsZ0JBQU0sY0FBYyxPQUFPO0FBQzNCLGdCQUFNLGFBQWEsT0FBTztBQUMxQixjQUFJLEtBQUssb0JBQW9CLE1BQU07QUFDakMsa0JBQU0sSUFBSSxNQUFNLFlBQVksVUFBVSxLQUFLLFVBQVUsMkNBQTJDO0FBQUEsVUFDbEc7QUFDQSxlQUFLLGtCQUFrQjtBQUd2QixjQUFJLFdBQVcsQ0FBQyxHQUFHO0FBQ2pCLHVCQUFXLENBQUMsSUFBSSxXQUFXLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQztBQUMzQyx1QkFBVyxDQUFDLElBQUk7QUFBQSxVQUNsQjtBQUVBLG9CQUFVLFFBQVEsTUFBTSxrQ0FBa0MsVUFBVSxLQUFLLFVBQVUsTUFBTTtBQUV6RixnQkFBTSxnQkFBZ0IsS0FBSyxJQUFJO0FBRS9CLGVBQUssZ0JBQWdCLENBQUM7QUFDdEIsY0FBSTtBQUNGLGdCQUFJLGVBQWU7QUFDakIsbUJBQUssT0FBTyxlQUFlLFlBQVk7QUFBQSxZQUN6QztBQUVBLHdCQUFZLFNBQVMsV0FBVyxDQUFDLENBQUM7QUFDbEMsbUJBQU87QUFBQSxVQUNULFNBQVMsR0FBRztBQUNWLG1CQUFPLEtBQUssUUFBUSxRQUFRLHFCQUFxQixVQUFVLEtBQUssVUFBVSxhQUFhLENBQUMsRUFBRSxDQUFDO0FBQzNGLG1CQUFPO0FBQUEsVUFDVCxVQUFFO0FBQ0EsZ0JBQUksZUFBZTtBQUNqQixxQkFBTztBQUFBLGdCQUNMLEtBQUssT0FDRixjQUFjLEVBQ2Q7QUFBQSxrQkFBSyxDQUFDLFFBQ0wsTUFBTSxxQ0FBcUMsVUFBVSxLQUFLLFVBQVUsTUFBTSxJQUFJLE9BQU8sS0FBSztBQUFBLGdCQUM1RjtBQUFBLGNBQ0o7QUFBQSxZQUNGO0FBRUEsdUJBQVcsUUFBUSxLQUFLLGVBQWU7QUFDckMsbUJBQUssZUFBZSxRQUFRLEtBQUssRUFBRTtBQUFBLFlBQ3JDO0FBQ0EsaUJBQUssZ0JBQWdCLENBQUM7QUFDdEIsaUJBQUssa0JBQWtCO0FBQUEsVUFDekI7QUFBQSxRQUNGO0FBQUE7QUFBQSxRQUdBLGVBQWUsV0FBbUIsT0FBZSxRQUFtQixNQUFzQjtBQUN4RixjQUFJLDRCQUE0QixLQUFLLDJCQUEyQixJQUFJLFNBQVM7QUFDN0UsY0FBSSxDQUFDLDJCQUEyQjtBQUM5Qix3Q0FBNEIsb0JBQUksSUFBSTtBQUNwQyxpQkFBSywyQkFBMkIsSUFBSSxXQUFXLHlCQUF5QjtBQUFBLFVBQzFFO0FBT0EsZ0JBQU0saUJBQWlCLDBCQUEwQixJQUFJLEtBQUs7QUFDMUQsZ0JBQU0sS0FBSyxLQUFLLGVBQWUsdUJBQXVCLFFBQVEsTUFBTSxjQUFjO0FBQ2xGLG9DQUEwQixJQUFJLE9BQU8sQ0FBQyxJQUFJLE1BQU0sQ0FBQztBQUNqRCxpQkFBTztBQUFBLFFBQ1Q7QUFBQSxRQUNBLGtCQUFrQixXQUF5QjtBQUN6QyxnQkFBTSw0QkFBNEIsS0FBSywyQkFBMkIsSUFBSSxTQUFTO0FBQy9FLGNBQUksMkJBQTJCO0FBQzdCLHNDQUEwQixRQUFRLENBQUMsZUFBZSxLQUFLLGVBQWUseUJBQXlCLFdBQVcsQ0FBQyxDQUFDLENBQUM7QUFDN0csaUJBQUssMkJBQTJCLE9BQU8sU0FBUztBQUFBLFVBQ2xEO0FBQUEsUUFDRjtBQUFBLFFBQ0EsVUFBVSxXQUE4QjtBQUN0QyxnQkFBTSxVQUFVLEtBQUssZUFBZSxJQUFJLFNBQVM7QUFDakQsY0FBSSxDQUFDLFNBQVM7QUFDWixrQkFBTSxJQUFJLE1BQU0sMkJBQTJCLFNBQVMsRUFBRTtBQUFBLFVBQ3hEO0FBQ0EsaUJBQU8sUUFBUTtBQUFBLFFBQ2pCO0FBQUEsUUFDQSxpQkFDRSxXQUNBLE1BQ0EsTUFDZ0M7QUFDaEMsaUJBQU8sWUFBWTtBQUNqQixrQkFBTSxPQUFPLE1BQU0sZ0JBQWdCLE1BQU0sV0FBVyxJQUFJO0FBQ3hELG1CQUFPLFdBQVcsS0FBSyxRQUFRLElBQUk7QUFBQSxVQUNyQztBQUFBLFFBQ0Y7QUFBQTtBQUFBLFFBRUEsZUFBZSxPQUFxQjtBQUNsQyxjQUFJLEtBQUssY0FBYyxpQkFBaUI7QUFDdEM7QUFBQSxVQUNGO0FBR0EsVUFBQyxLQUFLLG1CQUEyQixlQUFlLEtBQUssVUFBVSxLQUFLO0FBQUEsUUFDdEU7QUFBQSxRQUNBLGVBQXFCO0FBQ25CLGVBQUssWUFBWTtBQUNqQixjQUNFLEtBQUssSUFBSSxPQUFPLFdBQVcsU0FBUyxjQUNuQyxPQUFPLEtBQUssSUFBSSxVQUFVLGNBQWMsS0FBSyxJQUFJLEtBQUssUUFBUSxLQUFLLElBQUksUUFDeEU7QUFDQSxnQkFBSSxLQUFLLE9BQU8sU0FBUyxJQUFJLHFEQUFxRCxHQUFHO0FBQ25GLG1CQUFLLFlBQVk7QUFBQSxZQUNuQixXQUFXLEtBQUssT0FBTyxTQUFTLElBQUksaUJBQWlCLEdBQUc7QUFDdEQsbUJBQUssWUFBWTtBQUFBLFlBQ25CO0FBRUEsZ0JBQUksS0FBSyxjQUFjLFVBQVUsT0FBTyxLQUFLLGFBQWEsYUFBYTtBQUNyRSxtQkFBSyxXQUFXLEtBQUssT0FBTyxlQUFlO0FBQUEsZ0JBQ3pDLE1BQU07QUFBQSxnQkFDTixPQUFPLEtBQUssb0JBQW9CO0FBQUEsY0FDbEMsQ0FBQztBQUNELG1CQUFLLHFCQUFxQixLQUFLLE9BQU87QUFBQTtBQUFBLGdCQUVwQyxFQUFFLE1BQU0sS0FBSyxvQkFBb0IsSUFBSSxHQUFHLE9BQU8sZUFBZSxXQUFXLGVBQWUsY0FBYztBQUFBLGNBQ3hHO0FBQUEsWUFDRjtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQUEsUUFFQSxlQUFxQjtBQUNuQixvQkFBVSxRQUFRLGNBQWM7QUFDaEMsY0FBSSxDQUFDLEtBQUssb0JBQW9CLElBQUksS0FBSyxnQkFBaUIsR0FBRztBQUN6RCxpQkFBSyxvQkFBb0IsSUFBSSxLQUFLLGtCQUFtQixDQUFDLENBQUM7QUFBQSxVQUN6RDtBQUNBLGNBQUksQ0FBQyxLQUFLLHVCQUF1QixJQUFJLEtBQUssZ0JBQWlCLEdBQUc7QUFDNUQsaUJBQUssdUJBQXVCLElBQUksS0FBSyxrQkFBbUIsQ0FBQyxDQUFDO0FBQUEsVUFDNUQ7QUFFQSxlQUFLLE1BQU07QUFDWCxlQUFLLGdCQUFnQjtBQUFBLFFBQ3ZCO0FBQUEsUUFDQSxhQUFtQjtBQUNqQixvQkFBVSxRQUFRLFlBQVk7QUFFOUIsZUFBSyxNQUFNO0FBQ1gsZUFBSyxnQkFBZ0I7QUFBQSxRQUN2QjtBQUFBLFFBQ0EsU0FBZTtBQUNiLG9CQUFVLFFBQVEsUUFBUTtBQUMxQixlQUFLLGdCQUFnQjtBQUNyQixnQkFBTSxxQkFBcUIsS0FBSyxvQkFBb0IsSUFBSSxLQUFLLGdCQUFpQjtBQUM5RSxnQkFBTSx3QkFBd0IsS0FBSyx1QkFBdUIsSUFBSSxLQUFLLGdCQUFpQjtBQUNwRixnQkFBTSxTQUFTLG1CQUFvQjtBQUNuQyxlQUFLLGlCQUFpQixDQUFDO0FBQ3ZCLG1CQUFTLElBQUksR0FBRyxJQUFJLFFBQVEsS0FBSztBQUMvQixrQkFBTSxxQkFBcUIsS0FBSyxzQkFBc0I7QUFDdEQsa0JBQU0sVUFBVSxtQkFBb0IsQ0FBQztBQUNyQyxpQkFBSyxlQUFlLEtBQUssd0JBQXdCLENBQUM7QUFDbEQsK0JBQW1CLFlBQVksUUFBUSxlQUFlO0FBQ3RELCtCQUFtQixhQUFhLEdBQUcsUUFBUSxTQUFTO0FBQ3BELCtCQUFtQixtQkFBbUIsR0FBRyxRQUFRLGFBQWE7QUFDOUQsaUJBQUssZUFBZSxLQUFLLHdCQUF3QixJQUFJLENBQUM7QUFDdEQsaUJBQUs7QUFDTCxnQkFBSSxLQUFLLGNBQWMsUUFBUTtBQUM3QixtQkFBSyxlQUFlLEtBQUssc0JBQXVCLENBQUMsQ0FBQztBQUFBLFlBQ3BEO0FBQ0EsZ0JBQUksS0FBSyx5QkFBeUIsS0FBSyxxQkFBcUIsS0FBSyxjQUFjLGFBQWE7QUFDMUYsbUJBQUssZUFBZTtBQUFBLFlBQ3RCO0FBQ0EsZ0JBQUksS0FBSyx5QkFBeUIsS0FBSyxtQkFBbUI7QUFDeEQsbUJBQUssTUFBTTtBQUFBLFlBQ2I7QUFBQSxVQUNGO0FBRUEsZUFBSyxNQUFNO0FBQ1gsZUFBSyxnQkFBZ0I7QUFBQSxRQUN2QjtBQUFBLFFBRUEsa0JBQXdCO0FBQ3RCLGVBQUssZUFBZSxnQkFBZ0I7QUFBQSxRQUN0QztBQUFBLFFBRUEsaUJBQWlCLFdBQXlCO0FBQ3hDLGVBQUssa0JBQWtCLFNBQVM7QUFDaEMsY0FBSSxLQUFLLG9CQUFvQixJQUFJLFNBQVMsR0FBRztBQUMzQyxpQkFBSyxvQkFBb0IsT0FBTyxTQUFTO0FBQUEsVUFDM0M7QUFDQSxjQUFJLEtBQUssdUJBQXVCLElBQUksU0FBUyxHQUFHO0FBQzlDLGlCQUFLLHVCQUF1QixPQUFPLFNBQVM7QUFBQSxVQUM5QztBQUNBLGVBQUssZUFBZSxpQkFBaUIsU0FBUztBQUFBLFFBQ2hEO0FBQUEsUUFFQSxXQUFXLFdBQXlCO0FBQ2xDLGVBQUssbUJBQW1CO0FBQ3hCLGVBQUssYUFBYTtBQUFBLFFBQ3BCO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQzc1QkE7QUFBQTtBQUFBO0FBQUE7QUFBQSxNQWtCTSxnQkFvREEsb0JBcUhPO0FBM0xiO0FBQUE7QUFBQTtBQUtBO0FBS0E7QUFFQTtBQUVBO0FBSUEsTUFBTSxpQkFBTixNQUFNLGdCQUFxQztBQUFBLFFBQ3pDLFlBQ1UsUUFDUSxVQUNBLE1BQ0EsTUFDaEI7QUFKUTtBQUNRO0FBQ0E7QUFDQTtBQUFBLFFBQ2Y7QUFBQSxRQUVILGtCQUFnQztBQUM5QixjQUFJLEtBQUssNEJBQTZCO0FBQ3BDLGtCQUFNLElBQUksTUFBTSxtQkFBbUI7QUFBQSxVQUNyQztBQUNBLGdCQUFNLGVBQWUsVUFBVSxLQUFLLEtBQUssSUFBSTtBQUM3QyxpQkFBTyxpQkFBaUIsSUFDcEIsSUFBSSxhQUFhLElBQ2pCLElBQUksYUFBYSxLQUFLLE9BQU8sTUFBTSxRQUFRLEtBQUssTUFBTSxZQUFZO0FBQUEsUUFDeEU7QUFBQSxRQUVBLG1CQUFrQztBQUNoQyxjQUFJLEtBQUssNEJBQTZCO0FBQ3BDLGtCQUFNLElBQUksTUFBTSxtQkFBbUI7QUFBQSxVQUNyQztBQUNBLGdCQUFNLGVBQWUsVUFBVSxLQUFLLEtBQUssSUFBSTtBQUM3QyxpQkFBTyxpQkFBaUIsSUFDcEIsSUFBSSxjQUFjLElBQ2xCLElBQUksY0FBYyxLQUFLLE9BQU8sTUFBTSxRQUFRLEtBQUssTUFBTSxZQUFZO0FBQUEsUUFDekU7QUFBQSxRQUVBLGdCQUE0QjtBQUMxQixjQUFJLEtBQUssNEJBQTZCO0FBQ3BDLGtCQUFNLElBQUksTUFBTSxtQkFBbUI7QUFBQSxVQUNyQztBQUNBLGdCQUFNLGVBQWUsVUFBVSxLQUFLLEtBQUssSUFBSTtBQUM3QyxpQkFBTyxpQkFBaUIsSUFBSSxJQUFJLFdBQVcsSUFBSSxJQUFJLFdBQVcsS0FBSyxPQUFPLE1BQU0sUUFBUSxLQUFLLE1BQU0sWUFBWTtBQUFBLFFBQ2pIO0FBQUEsUUFFQSxpQkFBOEI7QUFDNUIsY0FBSSxLQUFLLGlDQUFpQyxLQUFLLDZCQUE4QjtBQUMzRSxrQkFBTSxJQUFJLE1BQU0sbUJBQW1CO0FBQUEsVUFDckM7QUFDQSxnQkFBTSxlQUFlLFVBQVUsS0FBSyxLQUFLLElBQUk7QUFDN0MsaUJBQU8saUJBQWlCLElBQUksSUFBSSxZQUFZLElBQUksSUFBSSxZQUFZLEtBQUssT0FBTyxNQUFNLFFBQVEsS0FBSyxNQUFNLFlBQVk7QUFBQSxRQUNuSDtBQUFBLFFBRUEsUUFBUSxTQUF3QztBQUM5QyxjQUFJLFVBQVUsS0FBSyxPQUFPLE1BQU0sVUFBVSxLQUFLLEtBQUssSUFBSSxHQUFHO0FBQ3pELGtCQUFNLElBQUksTUFBTSxtQkFBbUI7QUFBQSxVQUNyQztBQUNBLGlCQUFPLElBQUksZ0JBQWUsS0FBSyxRQUFRLEtBQUssVUFBVSxLQUFLLE1BQU0sT0FBTztBQUFBLFFBQzFFO0FBQUEsTUFDRjtBQUVBLE1BQU0scUJBQU4sTUFBbUQ7QUFBQSxRQWFqRCxZQUNVLFFBQ0EsU0FDUixtQkFDQTtBQUhRO0FBQ0E7QUFKVixlQUFRLG1CQUFtQjtBQUMzQixlQUFRLGlCQUFpQjtBQU12QixlQUFLLGNBQWMsUUFBUTtBQUczQixnQkFBTSxVQUFVLE9BQU87QUFDdkIsY0FBSSxZQUFZLG9CQUFvQixPQUFPO0FBQzNDLGdCQUFNLE9BQU8sWUFBWSxJQUFJLFFBQVE7QUFDckMsZUFBSyxrQkFBa0IsT0FBTyxPQUFPLFNBQVMsVUFBVSxhQUFhLElBQUksQ0FBQztBQUMxRSxnQkFBTSxhQUFhLE9BQU8sT0FBTyxTQUFTLFVBQVUsYUFBYSxJQUFJLENBQUM7QUFDdEUsZUFBSyxjQUFjLE9BQU8sT0FBTyxTQUFTLFVBQVUsYUFBYSxJQUFJLENBQUM7QUFDdEUsZUFBSyxtQkFBbUIsT0FBTyxPQUFPLFNBQVMsVUFBVSxhQUFhLEdBQUcsQ0FBQztBQUMxRSxlQUFLLGlCQUFpQixPQUFPLE9BQU8sU0FBUyxVQUFVLGFBQWEsSUFBSSxDQUFDO0FBRXpFLGdCQUFNLFNBQXVCLENBQUM7QUFDOUIsbUJBQVMsSUFBSSxHQUFHLElBQUksWUFBWSxLQUFLO0FBQ25DLGtCQUFNLFdBQVcsT0FBTyxPQUFPLFNBQVMsVUFBVSxhQUFhLElBQUksQ0FBQztBQUNwRSxrQkFBTSxPQUFPLE9BQU8sT0FBTyxTQUFTLFVBQVUsYUFBYSxHQUFHLENBQUM7QUFDL0Qsa0JBQU0sTUFBTSxPQUFPLE9BQU8sU0FBUyxVQUFVLGFBQWEsSUFBSSxDQUFDO0FBQy9ELGtCQUFNLE9BQWlCLENBQUM7QUFDeEIscUJBQVMsSUFBSSxHQUFHLElBQUksS0FBSyxLQUFLO0FBQzVCLG1CQUFLLEtBQUssT0FBTyxPQUFPLFNBQVMsVUFBVSxhQUFhLElBQUksQ0FBQyxDQUFDO0FBQUEsWUFDaEU7QUFDQSxtQkFBTyxLQUFLLElBQUksZUFBZSxRQUFRLFVBQVUsTUFBTSxJQUFJLENBQUM7QUFBQSxVQUM5RDtBQUNBLGVBQUssU0FBUztBQUFBLFFBQ2hCO0FBQUEsUUFyQ0EsSUFBSSxtQkFBK0M7QUFDakQsaUJBQU8sS0FBSyxRQUFRO0FBQUEsUUFDdEI7QUFBQSxRQUNBLElBQUksbUJBQStCO0FBQ2pDLGlCQUFPLEtBQUssT0FBTyxPQUFPLFNBQVMsS0FBSyxrQkFBa0IsS0FBSyxtQkFBbUIsS0FBSyxjQUFjO0FBQUEsUUFDdkc7QUFBQSxRQWtDQSxRQUFRLFNBQXNCLHNCQUF5RTtBQUVyRyxnQkFBTSxlQUNKLHNCQUFzQixRQUFRLElBQUksQ0FBQyxNQUFPLE9BQU8sTUFBTSxXQUFXLEtBQUssT0FBTyxDQUFDLElBQUksQ0FBRSxLQUFLLEtBQUs7QUFFakcsZ0JBQU0sZ0JBQWdCLHNCQUFzQixXQUFXLENBQUM7QUFDeEQsZ0JBQU0scUJBQXFCLENBQUMsT0FBZSxVQUFrQixTQUMzRCxJQUFJLGVBQWUsS0FBSyxRQUFRLFVBQVUsS0FBSyxPQUFPLE9BQU8sSUFBSSxHQUFHLElBQUk7QUFDMUUsZ0JBQU0sd0JBQXdCLENBQUMsVUFBa0IsU0FBd0M7QUFDdkYsa0JBQU0sYUFBYSwyQkFBMkIsVUFBVSxJQUFJO0FBQzVELGdCQUFJLENBQUMsWUFBWTtBQUNmLG9CQUFNLElBQUksTUFBTSwwQkFBMEIsUUFBUSxFQUFFO0FBQUEsWUFDdEQ7QUFDQSxrQkFBTSxZQUFZLGFBQWEsSUFBSSxLQUFLLFFBQVEsZUFBZSxPQUFPLFVBQVUsRUFBRSxLQUFLO0FBQ3ZGLG1CQUFPLElBQUksZUFBZSxLQUFLLFFBQVEsVUFBVSxXQUFXLElBQUk7QUFBQSxVQUNsRTtBQUNBLGlCQUFPLEtBQUssUUFBUTtBQUFBLFlBQ2xCO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0EsS0FBSztBQUFBLFVBQ1A7QUFBQSxRQUNGO0FBQUEsUUFFQSxPQUFPLE9BQWUsTUFBaUM7QUFDckQsZ0JBQU0sUUFBUSxLQUFLLE9BQU8sVUFBVTtBQUNwQyxjQUFJO0FBQ0Ysa0JBQU0sVUFBVSxLQUFLLE9BQU87QUFDNUIsa0JBQU0sT0FBTyxZQUFZLElBQUksUUFBUTtBQUNyQyxrQkFBTSxPQUFPLEtBQUssT0FBTztBQUFBLGVBQVksSUFBSSxLQUFLLFVBQVU7QUFBQTtBQUFBLFlBQTRCO0FBQ3BGLGlCQUFLLE9BQU8sU0FBUyxNQUFNLEtBQUssUUFBUSxJQUFJO0FBQzVDLHFCQUFTLElBQUksR0FBRyxJQUFJLEtBQUssUUFBUSxLQUFLO0FBQ3BDLG1CQUFLLE9BQU8sU0FBUyxPQUFPLFdBQVcsSUFBSSxJQUFJLEtBQUssQ0FBQyxHQUFHLElBQUk7QUFBQSxZQUM5RDtBQUNBLG1CQUFPLEtBQUssT0FBTyxZQUFhLEtBQUssaUJBQWlCLE9BQU8sSUFBSTtBQUFBLFVBQ25FLFNBQVMsR0FBRztBQUNWLGtCQUFNLElBQUk7QUFBQSxjQUNSLHNDQUFzQyxLQUFLLGdCQUFnQixJQUFJLDhHQUVuRCxDQUFDO0FBQUEsWUFDZjtBQUFBLFVBQ0YsVUFBRTtBQUNBLGlCQUFLLE9BQU8sYUFBYSxLQUFLO0FBQUEsVUFDaEM7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQTBCTyxNQUFNLE9BQU8sT0FDbEIsTUFDQSxRQUNBQyxNQUNBLGVBQ2tCO0FBQ2xCLGNBQU0sV0FBVyxPQUFPO0FBQ3hCLFlBQUksQ0FBQyxVQUFVO0FBQ2IsZ0JBQU0sSUFBSSxNQUFNLG1GQUFtRjtBQUFBLFFBQ3JHO0FBRUEsWUFBSSxTQUFTLFVBQVU7QUFDckIsY0FBSSxNQUEyQjtBQUU3QixrQkFBTSxvQkFBb0IsOERBQTRCO0FBQ3RELGtCQUFNLFVBQVUsSUFBSSxrQkFBa0I7QUFDdEMsa0JBQU0sUUFBUSxXQUFXQSxNQUFLLFVBQVc7QUFFekMscUJBQVMsVUFBVTtBQUFBO0FBQUEsY0FFakI7QUFBQTtBQUFBLGNBR0EsQ0FBQyxTQUFpQixRQUFRLE1BQU0sT0FBTyxJQUFJLENBQUM7QUFBQTtBQUFBLGNBRzVDLENBQUMsUUFBZ0IsUUFBUSxLQUFLLEdBQUc7QUFBQTtBQUFBLGNBR2pDLENBQUMsS0FBYSxLQUFhLE1BQWMsY0FBYyxVQUFVO0FBQy9ELG9CQUFJLGFBQWE7QUFDZjtBQUFBLG9CQUNFO0FBQUEsb0JBQ0EsTUFBTSxrQ0FBa0MsT0FBTyxHQUFHLENBQUMsU0FBUyxPQUFPLEdBQUcsQ0FBQyxVQUFVLE9BQU8sSUFBSSxDQUFDO0FBQUEsa0JBQy9GO0FBQ0EsMEJBQVEsT0FBTyxPQUFPLEdBQUcsR0FBRyxPQUFPLEdBQUcsQ0FBQztBQUFBLGdCQUN6QyxPQUFPO0FBQ0w7QUFBQSxvQkFDRTtBQUFBLG9CQUNBLE1BQ0UseUNBQXlDLE9BQU8sR0FBRyxDQUFDLGVBQWUsT0FBTyxHQUFHLENBQUMsVUFBVSxPQUFPLElBQUksQ0FBQztBQUFBLGtCQUN4RztBQUNBLHdCQUFNLE9BQU8sT0FBTyxPQUFPLFNBQVMsT0FBTyxRQUFRLENBQUMsR0FBRyxPQUFPLFFBQVEsQ0FBQyxJQUFJLE9BQU8sSUFBSSxDQUFDO0FBQ3ZGLDBCQUFRLE9BQU8sT0FBTyxHQUFHLEdBQUcsSUFBSTtBQUFBLGdCQUNsQztBQUFBLGNBQ0Y7QUFBQTtBQUFBLGNBR0EsT0FBTyxXQUFtQixZQUFvQixTQUFnQztBQUM1RTtBQUFBLGtCQUNFO0FBQUEsa0JBQ0EsTUFBTSx3Q0FBd0MsU0FBUyxnQkFBZ0IsVUFBVSxVQUFVLElBQUk7QUFBQSxnQkFDakc7QUFFQSxzQkFBTSxRQUFRO0FBQUEsa0JBQVMsT0FBTyxTQUFTO0FBQUEsa0JBQUcsTUFDeEMsT0FBTyxPQUFPLFNBQVMsT0FBTyxVQUFVLE1BQU0sR0FBRyxPQUFPLGFBQWEsSUFBSSxNQUFNLENBQUM7QUFBQSxnQkFDbEY7QUFBQSxjQUNGO0FBQUE7QUFBQSxjQUdBLENBQUMsWUFBb0IsVUFBa0IsY0FDckMsUUFBUTtBQUFBLGdCQUNOO0FBQUEsZ0JBQ0EsT0FBTyxRQUFRO0FBQUEsZ0JBQ2Y7QUFBQSxnQkFDQSxPQUFPLGFBQWEsT0FBTyxpQkFBa0IsT0FBTyxRQUFRLENBQUMsQ0FBQztBQUFBLGNBQ2hFO0FBQUE7QUFBQSxjQUdGLENBQUMsV0FBbUIsUUFBUSxjQUFjLE1BQU07QUFBQTtBQUFBLGNBR2hELENBQUMsUUFBZ0IsbUJBQTJCLGVBQXVCLFdBQTBDO0FBQzNHO0FBQUEsa0JBQ0U7QUFBQSxrQkFDQSxNQUNFLG1DQUFtQyxhQUFhLFlBQVksTUFBTSx1QkFBdUIsaUJBQWlCO0FBQUEsZ0JBQzlHO0FBQ0Esc0JBQU0sVUFBVSxJQUFJLG1CQUFtQixRQUFRLFNBQVMsT0FBTyxpQkFBaUIsQ0FBQztBQUNqRix1QkFBTyxRQUFRLGNBQWMsT0FBTyxNQUFNLEdBQUcsU0FBUyxNQUFNO0FBQUEsY0FDOUQ7QUFBQTtBQUFBLGNBRUEsTUFBTSxRQUFRLGFBQWE7QUFBQTtBQUFBLGNBRTNCLE1BQU0sUUFBUSxXQUFXO0FBQUE7QUFBQSxjQUV6QixNQUFNLFFBQVEsT0FBTztBQUFBLFlBQ3ZCLENBQUM7QUFBQSxVQUNIO0FBQUEsUUFDRixPQUFPO0FBQ0wsZ0JBQU0sVUFBVSxJQUFJLGFBQWFBLElBQUc7QUFDcEMsbUJBQVMsU0FBUztBQUFBLFlBQ2hCO0FBQUE7QUFBQSxZQUVBLE1BQU0sUUFBUSxnQkFBZ0I7QUFBQTtBQUFBLFlBRTlCLENBQUMsYUFBcUIsUUFBUSxnQkFBZ0IsUUFBUTtBQUFBO0FBQUEsWUFFdEQsT0FBTyxXQUErQixVQUFrQixjQUFzQixPQUFpQixZQUM3RixRQUFRLGFBQWEsV0FBVyxVQUFVLGNBQWMsT0FBTyxPQUFPO0FBQUE7QUFBQSxZQUV4RSxDQUFDLFVBQWtCLFNBQXFCO0FBQ3RDLHNCQUFRLGFBQWEsVUFBVSxJQUFJO0FBQUEsWUFDckM7QUFBQTtBQUFBLFlBRUEsT0FBTyxVQUFrQixjQUE2QyxRQUFRLGVBQWUsVUFBVSxTQUFTO0FBQUEsVUFDbEgsQ0FBQztBQUFBLFFBQ0g7QUFBQSxNQUNGO0FBQUE7QUFBQTs7O0FDdlNBLE1BaUZNLFNBV08sYUFXQSxRQThHUCxnQkFPQSw0QkFpQkEsK0JBaURPLHdCQWtCQSxlQTZNQSxnQkErQkEsMEJBcUlBLEtBcVlBLGNBZ0JBO0FBdGpDYjtBQUFBO0FBQUE7QUFnQkE7QUFDQTtBQUNBO0FBVUE7QUFDQTtBQUNBO0FBbURBLE1BQU0sVUFBVSxDQUFDLFlBQW9CLGlCQUErQjtBQUNsRSxjQUFNLFlBQVksWUFBWSxFQUFFLFNBQVMsWUFBWSxZQUFZO0FBQ2pFLFlBQUksY0FBYyxHQUFHO0FBQ25CLHlCQUFlLCtCQUErQjtBQUFBLFFBQ2hEO0FBQUEsTUFDRjtBQU1PLE1BQU0sY0FBYyxPQUFPQyxTQUE0QjtBQUU1RCxnQkFBUUEsS0FBSSxLQUFLLFlBQWEscUJBQXFCQSxLQUFJLFFBQVEsQ0FBQztBQUFBLE1BQ2xFO0FBUU8sTUFBTSxTQUFTLE9BQU9BLE1BQVUsV0FBa0M7QUFFdkUsb0JBQVksRUFBRSxZQUFZO0FBRTFCLFlBQUksV0FBVyxZQUFZLE9BQTBCO0FBQ25ELHNCQUFZLEVBQUUsV0FBWSxDQUFDLFdBQVc7QUFDcEMsWUFBQUEsS0FBSSxPQUFPLFNBQVM7QUFBQSxVQUN0QixDQUFDO0FBQUEsUUFDSDtBQUVBLFlBQUksTUFBMEI7QUFFNUIsZ0JBQU0sV0FBVywwQ0FBdUI7QUFFeEMsY0FBSSxXQUFXLFlBQVksTUFBMkI7QUFFcEQsZ0JBQUksT0FBTyxjQUFjLGVBQWUsQ0FBQyxVQUFVLEtBQUs7QUFDdEQsb0JBQU0sSUFBSSxNQUFNLGdEQUFnRDtBQUFBLFlBQ2xFO0FBRUEsZ0JBQUksVUFBVUEsS0FBSSxPQUFPO0FBQ3pCLGdCQUFJLENBQUMsU0FBUztBQUVaLG9CQUFNLGtCQUFrQkEsS0FBSSxPQUFPO0FBQ25DLGtCQUNFLG9CQUFvQixVQUNwQixvQkFBb0IsZUFDcEIsb0JBQW9CLG9CQUNwQjtBQUNBLHNCQUFNLElBQUksTUFBTSxxQ0FBcUMsZUFBZSxHQUFHO0FBQUEsY0FDekU7QUFDQSxvQkFBTSx1QkFBdUJBLEtBQUksT0FBTztBQUN4QyxrQkFBSSx5QkFBeUIsVUFBYSxPQUFPLHlCQUF5QixXQUFXO0FBQ25GLHNCQUFNLElBQUksTUFBTSwwQ0FBMEMsb0JBQW9CLEdBQUc7QUFBQSxjQUNuRjtBQUNBLHdCQUFVLE1BQU0sVUFBVSxJQUFJLGVBQWUsRUFBRSxpQkFBaUIscUJBQXFCLENBQUM7QUFDdEYsa0JBQUksQ0FBQyxTQUFTO0FBQ1osc0JBQU0sSUFBSTtBQUFBLGtCQUNSO0FBQUEsZ0JBRUY7QUFBQSxjQUNGO0FBQUEsWUFDRixPQUFPO0FBRUwsa0JBQ0UsT0FBTyxRQUFRLFdBQVcsWUFDMUIsT0FBTyxRQUFRLGFBQWEsWUFDNUIsT0FBTyxRQUFRLGtCQUFrQixZQUNqQztBQUNBLHNCQUFNLElBQUksTUFBTSxrRkFBa0Y7QUFBQSxjQUNwRztBQUFBLFlBQ0Y7QUFFQSxrQkFBTSxTQUFTLFVBQVUsWUFBWSxHQUFHQSxNQUFLLE9BQU87QUFBQSxVQUN0RDtBQUNBLGNBQUksV0FBVyxTQUFTO0FBRXRCLGdCQUFJLE9BQU8sY0FBYyxlQUFlLENBQUUsVUFBeUMsSUFBSTtBQUNyRixvQkFBTSxJQUFJLE1BQU0sK0NBQStDO0FBQUEsWUFDakU7QUFFQSxrQkFBTSxTQUFTLFNBQVMsWUFBWSxHQUFHQSxJQUFHO0FBQUEsVUFDNUM7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQThDQSxNQUFNLGlCQUFpQixvQkFBSSxJQUE2QjtBQU94RCxNQUFNLDZCQUE2QixDQUFDLGtCQUE0QztBQUM5RSxjQUFNQyxRQUFPLFlBQVk7QUFDekIsY0FBTSxRQUFRQSxNQUFLLFVBQVU7QUFDN0IsWUFBSTtBQUNGLGdCQUFNLFVBQVVBLE1BQUs7QUFDckIsZ0JBQU0sYUFBYUEsTUFBSyxXQUFXLElBQUksT0FBTztBQUM5QyxnQkFBTSxZQUFZQSxNQUFLLHdCQUF3QixlQUFlLFlBQVksYUFBYSxPQUFPO0FBQzlGLGNBQUksY0FBYyxHQUFHO0FBQ25CLDJCQUFlLHVDQUF1QztBQUFBLFVBQ3hEO0FBQ0EsZ0JBQU0sT0FBTyxZQUFZLElBQUksUUFBUTtBQUNyQyxpQkFBTyxDQUFDLE9BQU9BLE1BQUssU0FBUyxZQUFZLElBQUksQ0FBQyxHQUFHLE9BQU9BLE1BQUssU0FBUyxhQUFhLFNBQVMsSUFBSSxDQUFDLENBQUM7QUFBQSxRQUNwRyxVQUFFO0FBQ0EsVUFBQUEsTUFBSyxhQUFhLEtBQUs7QUFBQSxRQUN6QjtBQUFBLE1BQ0Y7QUFFQSxNQUFNLGdDQUFnQyxDQUNwQyxlQUNBLFVBQzZFO0FBQzdFLGNBQU1BLFFBQU8sWUFBWTtBQUN6QixjQUFNLFFBQVFBLE1BQUssVUFBVTtBQUM3QixZQUFJLGlCQUFpQjtBQUNyQixZQUFJO0FBQ0YsZ0JBQU0sVUFBVUEsTUFBSztBQUNyQixnQkFBTSxhQUFhQSxNQUFLLFdBQVcsSUFBSSxPQUFPO0FBQzlDLGdCQUFNLFlBQVlBLE1BQUssMkJBQTJCLGVBQWUsT0FBTyxZQUFZLGFBQWEsT0FBTztBQUN4RyxjQUFJLGNBQWMsR0FBRztBQUNuQiwyQkFBZSwwQ0FBMEM7QUFBQSxVQUMzRDtBQUNBLGdCQUFNLGFBQWEsT0FBT0EsTUFBSyxTQUFTLFlBQVksR0FBRyxDQUFDO0FBQ3hELDJCQUFpQixPQUFPQSxNQUFLLFNBQVMsYUFBYSxTQUFTLEdBQUcsQ0FBQztBQUVoRSxnQkFBTSxjQUFjQSxNQUFLLE9BQU8saUJBQWlCLENBQUM7QUFDbEQsY0FBSSxnQkFBZ0IsR0FBRztBQUNyQixtQkFBTyxDQUFDLFlBQVksQ0FBQztBQUFBLFVBQ3ZCO0FBR0EsZ0JBQU0sWUFBWUEsTUFBSyxRQUFRLGlCQUFpQixJQUFJLENBQUM7QUFFckQsZ0JBQU0sT0FBK0IsQ0FBQztBQUN0QyxtQkFBUyxJQUFJLEdBQUcsSUFBSSxXQUFXLEtBQUs7QUFDbEMsa0JBQU0sd0JBQXdCLE9BQU9BLE1BQUssU0FBUyxpQkFBaUIsSUFBSSxJQUFJLFNBQVMsR0FBRyxDQUFDO0FBQ3pGLGlCQUFLO0FBQUEsY0FDSCwwQkFBMEIsSUFDdEJBLE1BQUssYUFBYSxxQkFBcUIsSUFDdkMsT0FBT0EsTUFBSyxTQUFTLGlCQUFpQixLQUFLLElBQUksYUFBYSxTQUFTLEdBQUcsQ0FBQztBQUFBLFlBQy9FO0FBQUEsVUFDRjtBQUNBLGlCQUFPLENBQUMsWUFBWSxhQUFhLElBQUk7QUFBQSxRQUN2QyxVQUFFO0FBQ0EsVUFBQUEsTUFBSyxhQUFhLEtBQUs7QUFDdkIsY0FBSSxtQkFBbUIsR0FBRztBQUN4QixZQUFBQSxNQUFLLFNBQVMsY0FBYztBQUFBLFVBQzlCO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFRTyxNQUFNLHlCQUF5QixDQUFDLFVBQXdDO0FBQzdFLGNBQU1BLFFBQU8sWUFBWTtBQUN6QixjQUFNLGtCQUFrQkEsTUFBSyxRQUFRLE1BQU0sVUFBVTtBQUNyRCxZQUFJLG9CQUFvQixHQUFHO0FBQ3pCLGdCQUFNLElBQUksTUFBTSwrREFBK0QsTUFBTSxVQUFVLEdBQUc7QUFBQSxRQUNwRztBQUNBLFFBQUFBLE1BQUssT0FBTyxJQUFJLE9BQU8sZUFBZTtBQUN0QyxlQUFPLENBQUMsaUJBQWlCLE1BQU0sVUFBVTtBQUFBLE1BQzNDO0FBVU8sTUFBTSxnQkFBZ0IsT0FDM0IsV0FDQSxZQUN5QztBQUN6QyxZQUFJLGlCQUF5QjtBQUM3QixjQUFNQSxRQUFPLFlBQVk7QUFFekIsWUFBSSxNQUFNLFFBQVEsU0FBUyxHQUFHO0FBRTVCLFdBQUMsaUJBQWlCLGVBQWUsSUFBSTtBQUFBLFFBQ3ZDLFdBQVcsVUFBVSxXQUFXQSxNQUFLLE9BQU8sUUFBUTtBQUVsRCxXQUFDLGlCQUFpQixlQUFlLElBQUksQ0FBQyxVQUFVLFlBQVksVUFBVSxVQUFVO0FBQUEsUUFDbEYsT0FBTztBQUVMLFdBQUMsaUJBQWlCLGVBQWUsSUFBSSx1QkFBdUIsU0FBUztBQUFBLFFBQ3ZFO0FBRUEsWUFBSSxnQkFBZ0I7QUFDcEIsWUFBSSx1QkFBdUI7QUFDM0IsWUFBSSxrQkFBa0I7QUFDdEIsWUFBSSxTQUFtQixDQUFDO0FBQ3hCLGNBQU0sd0JBQXdCLENBQUM7QUFDL0IsY0FBTSx5QkFBeUIsQ0FBQztBQUVoQyxZQUFJO0FBQ0YsV0FBQyxzQkFBc0IsTUFBTSxJQUFJLE1BQU0sa0JBQWtCLE9BQU87QUFFaEUsY0FBSSxTQUFTLGdCQUFnQkEsTUFBSyxtQkFBbUI7QUFDbkQsa0JBQU0sa0JBQWtCLENBQUM7QUFDekIsdUJBQVcsUUFBUSxRQUFRLGNBQWM7QUFDdkMsb0JBQU0sT0FBTyxPQUFPLFNBQVMsV0FBVyxPQUFPLEtBQUs7QUFDcEQsOEJBQWdCO0FBQUEsZ0JBQ2QsU0FBUyxPQUFPLFNBQVMsV0FBVyxPQUFPLEtBQUssSUFBSSxFQUFFLEtBQUssQ0FBQyxTQUFTO0FBQ25FLGtCQUFBQSxNQUFLLGtCQUFrQixNQUFNLElBQUk7QUFBQSxnQkFDbkMsQ0FBQztBQUFBLGNBQ0g7QUFBQSxZQUNGO0FBR0Esa0JBQU0sUUFBUSxJQUFJLGVBQWU7QUFBQSxVQUNuQztBQUVBLHFCQUFXLFlBQVksU0FBUyxzQkFBc0IsQ0FBQyxHQUFHO0FBQ3hELGtCQUFNLGVBQWUsT0FBTyxhQUFhLFdBQVcsV0FBVyxTQUFTO0FBQ3hFLGdCQUFJLGlCQUFpQixTQUFTO0FBQzVCLGNBQUFBLE1BQUssMkJBQTJCO0FBQ2hDLGtCQUFJLE9BQU8sYUFBYSxVQUFVO0FBQ2hDLHNCQUFNLGVBQWU7QUFDckIsc0JBQU0sVUFBVyxjQUE2RDtBQUM5RSxzQkFBTSxZQUFhLGNBQXNEO0FBQ3pFLHNCQUFNLGFBQWMsY0FBdUQ7QUFDM0Usc0JBQU0sa0JBQW1CLGNBQXVEO0FBQ2hGLG9CQUFJLFNBQVM7QUFDWCxrQkFBQUEsTUFBSyxpQkFBaUI7QUFBQSxnQkFDeEIsV0FBVyxXQUFXO0FBQ3BCLGtCQUFBQSxNQUFLLGlCQUFpQixNQUFNQSxNQUFLLHFCQUFzQixTQUFTO0FBQUEsZ0JBQ2xFLE9BQU87QUFDTCxrQkFBQUEsTUFBSyxpQkFBaUIsTUFBTUEsTUFBSyxxQkFBc0IsRUFBRSxZQUFZLGdCQUFnQixDQUFDO0FBQUEsZ0JBQ3hGO0FBQUEsY0FDRixPQUFPO0FBQ0wsZ0JBQUFBLE1BQUssaUJBQWlCLE1BQU1BLE1BQUsscUJBQXNCO0FBQUEsY0FDekQ7QUFDQTtBQUFBLFlBQ0Y7QUFBQSxVQUNGO0FBRUEsMEJBQWdCLE1BQU1BLE1BQUssa0JBQWtCLGlCQUFpQixpQkFBaUIsb0JBQW9CO0FBQ25HLFVBQUFBLE1BQUssd0JBQXdCLGFBQWE7QUFDMUMsY0FBSSxrQkFBa0IsR0FBRztBQUN2QiwyQkFBZSx5QkFBeUI7QUFBQSxVQUMxQztBQUVBLFVBQUFBLE1BQUssc0JBQXNCO0FBRzNCLGNBQUlBLE1BQUssZ0JBQWdCO0FBQ3ZCLFlBQUFBLE1BQUssdUJBQXdCLGVBQWVBLE1BQUssY0FBYztBQUMvRCxZQUFBQSxNQUFLLGlCQUFpQjtBQUN0QixZQUFBQSxNQUFLLDJCQUEyQjtBQUFBLFVBQ2xDO0FBRUEsZ0JBQU0sQ0FBQyxZQUFZLFdBQVcsSUFBSSwyQkFBMkIsYUFBYTtBQUUxRSxnQkFBTSxxQkFBcUIsQ0FBQyxDQUFDLFNBQVM7QUFFdEMsZ0JBQU0sYUFBYSxDQUFDO0FBQ3BCLGdCQUFNLGNBQWMsQ0FBQztBQUNyQixnQkFBTSxnQkFBa0QsQ0FBQztBQUN6RCxnQkFBTSxpQkFBbUQsQ0FBQztBQUMxRCxnQkFBTSwyQkFBd0UsQ0FBQztBQUMvRSxtQkFBUyxJQUFJLEdBQUcsSUFBSSxZQUFZLEtBQUs7QUFDbkMsa0JBQU0sQ0FBQyxZQUFZLGFBQWEsS0FBSyxJQUFJLDhCQUE4QixlQUFlLENBQUM7QUFDdkYsZ0JBQUksZUFBZSxHQUFHO0FBQ3BCLDZCQUFlLDBCQUEwQjtBQUFBLFlBQzNDO0FBQ0Esa0NBQXNCLEtBQUssVUFBVTtBQUNyQyxrQkFBTSxPQUFPQSxNQUFLLGFBQWEsVUFBVTtBQUN6Qyx1QkFBVyxLQUFLLElBQUk7QUFDcEIsMEJBQWM7QUFBQSxjQUNaLGdCQUFnQixJQUNaLEVBQUUsTUFBTSxVQUFVLE1BQU0sSUFDeEIsRUFBRSxNQUFNLFVBQVUsTUFBTSxNQUFNLDJCQUEyQixXQUFXLEdBQUcsTUFBYztBQUFBLFlBQzNGO0FBQUEsVUFDRjtBQUNBLG1CQUFTLElBQUksR0FBRyxJQUFJLGFBQWEsS0FBSztBQUNwQyxrQkFBTSxDQUFDLFlBQVksYUFBYSxLQUFLLElBQUksOEJBQThCLGVBQWUsSUFBSSxVQUFVO0FBQ3BHLGdCQUFJLGVBQWUsR0FBRztBQUNwQiw2QkFBZSwyQkFBMkI7QUFBQSxZQUM1QztBQUNBLG1DQUF1QixLQUFLLFVBQVU7QUFDdEMsa0JBQU0sYUFBYUEsTUFBSyxhQUFhLFVBQVU7QUFDL0Msd0JBQVksS0FBSyxVQUFVO0FBQzNCLDJCQUFlO0FBQUEsY0FDYixnQkFBZ0IsSUFDWixFQUFFLE1BQU0sWUFBWSxVQUFVLE1BQU0sSUFDcEMsRUFBRSxNQUFNLFlBQVksVUFBVSxNQUFNLE1BQU0sMkJBQTJCLFdBQVcsR0FBRyxNQUFjO0FBQUEsWUFDdkc7QUFFQSxnQkFBSSxNQUEwQjtBQUM1QixrQkFBSSxzQkFBc0IsU0FBUyw0QkFBNEIsUUFBVztBQUN4RSx5Q0FBeUIsS0FBSyxZQUFZO0FBQzFDO0FBQUEsY0FDRjtBQUNBLG9CQUFNQyxZQUNKLE9BQU8sU0FBUyw0QkFBNEIsV0FDeEMsUUFBUSwwQkFDUCxTQUFTLDBCQUEwQixVQUFVLEtBQUs7QUFDekQsb0JBQU0sZ0JBQWdCRCxNQUFLO0FBQzNCLGtCQUFJQyxjQUFhLFNBQVMsaUJBQWlCLGNBQWMsZUFBZSxVQUFVLEdBQUc7QUFDbkYseUNBQXlCLEtBQUssc0JBQXNCO0FBQ3BEO0FBQUEsY0FDRjtBQUNBLGtCQUFJQSxjQUFhLFNBQVNBLGNBQWEsZ0JBQWdCQSxjQUFhLGdCQUFnQkEsY0FBYSxhQUFhO0FBQzVHLHNCQUFNLElBQUksTUFBTSw0Q0FBNENBLFNBQVEsR0FBRztBQUFBLGNBQ3pFO0FBQ0Esa0JBQUksc0JBQXNCQSxjQUFhLGNBQWM7QUFDbkQsc0JBQU0sSUFBSTtBQUFBLGtCQUNSLDRDQUE0Q0EsU0FBUTtBQUFBLGdCQUN0RDtBQUFBLGNBQ0Y7QUFDQSx1Q0FBeUIsS0FBS0EsU0FBUTtBQUFBLFlBQ3hDO0FBQUEsVUFDRjtBQUdBLGNBQUksZUFBc0M7QUFDMUMsY0FFRSx5QkFBeUIsS0FBSyxDQUFDLE1BQU0sTUFBTSxnQkFBZ0IsTUFBTSxlQUFlLE1BQU0sc0JBQXNCLEdBQzVHO0FBQ0EsOEJBQWtCRCxNQUFLLGtCQUFrQixhQUFhO0FBQ3RELGdCQUFJLG9CQUFvQixHQUFHO0FBQ3pCLDZCQUFlLDBCQUEwQjtBQUFBLFlBQzNDO0FBRUEsMkJBQWU7QUFBQSxjQUNiLFFBQVE7QUFBQSxjQUNSO0FBQUEsY0FDQSxpQ0FBaUMseUJBRTlCLElBQUksQ0FBQyxNQUFPLE1BQU0seUJBQXlCLGNBQWMsQ0FBRSxFQUMzRCxJQUFJLENBQUMsTUFBTSx5QkFBeUIsQ0FBQyxDQUFDO0FBQUEsWUFDM0M7QUFBQSxVQUNGO0FBRUEseUJBQWUsSUFBSSxlQUFlO0FBQUEsWUFDaEM7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQTtBQUFBLFVBQ0YsQ0FBQztBQUNELGlCQUFPLENBQUMsZUFBZSxZQUFZLGFBQWEsZUFBZSxjQUFjO0FBQUEsUUFDL0UsU0FBUyxHQUFHO0FBQ1YsZ0NBQXNCLFFBQVEsQ0FBQyxRQUFRQSxNQUFLLFNBQVMsR0FBRyxDQUFDO0FBQ3pELGlDQUF1QixRQUFRLENBQUMsUUFBUUEsTUFBSyxTQUFTLEdBQUcsQ0FBQztBQUUxRCxjQUFJLG9CQUFvQixHQUFHO0FBQ3pCLGdCQUFJQSxNQUFLLG1CQUFtQixlQUFlLE1BQU0sR0FBRztBQUNsRCw2QkFBZSwyQkFBMkI7QUFBQSxZQUM1QztBQUFBLFVBQ0Y7QUFFQSxjQUFJLGtCQUFrQixHQUFHO0FBQ3ZCLGdCQUFJQSxNQUFLLG1CQUFtQixhQUFhLE1BQU0sR0FBRztBQUNoRCw2QkFBZSx3QkFBd0I7QUFBQSxZQUN6QztBQUFBLFVBQ0Y7QUFDQSxnQkFBTTtBQUFBLFFBQ1IsVUFBRTtBQUNBLFVBQUFBLE1BQUssTUFBTSxlQUFlO0FBQzFCLGNBQUkseUJBQXlCLEdBQUc7QUFDOUIsZ0JBQUlBLE1BQUssMEJBQTBCLG9CQUFvQixNQUFNLEdBQUc7QUFDOUQsNkJBQWUsZ0NBQWdDO0FBQUEsWUFDakQ7QUFBQSxVQUNGO0FBQ0EsaUJBQU8sUUFBUSxDQUFDLFVBQVVBLE1BQUssTUFBTSxLQUFLLENBQUM7QUFHM0MsVUFBQUEsTUFBSyxzQkFBc0I7QUFBQSxRQUM3QjtBQUFBLE1BQ0Y7QUFFTyxNQUFNLGlCQUFpQixDQUFDLGNBQTRCO0FBQ3pELGNBQU1BLFFBQU8sWUFBWTtBQUN6QixjQUFNLFVBQVUsZUFBZSxJQUFJLFNBQVM7QUFDNUMsWUFBSSxDQUFDLFNBQVM7QUFDWixnQkFBTSxJQUFJLE1BQU0sK0NBQStDLFNBQVMsRUFBRTtBQUFBLFFBQzVFO0FBQ0EsY0FBTSxDQUFDLGVBQWUsdUJBQXVCLHdCQUF3QixnQkFBZ0Isa0JBQWtCLElBQUk7QUFFM0csWUFBSSxnQkFBZ0I7QUFDbEIsY0FBSSxvQkFBb0I7QUFDdEIsZ0JBQUlBLE1BQUssc0JBQXNCLGVBQWUsTUFBTSxNQUFNLEdBQUc7QUFDM0QsNkJBQWUsNEJBQTRCO0FBQUEsWUFDN0M7QUFBQSxVQUNGO0FBQ0EsY0FBSUEsTUFBSyxtQkFBbUIsZUFBZSxNQUFNLE1BQU0sR0FBRztBQUN4RCwyQkFBZSwyQkFBMkI7QUFBQSxVQUM1QztBQUFBLFFBQ0Y7QUFFQSxRQUFBQSxNQUFLLHVCQUF1QixTQUFTO0FBQ3JDLFFBQUFBLE1BQUssd0JBQXdCLFNBQVM7QUFDdEMsUUFBQUEsTUFBSyx5QkFBeUIsU0FBUztBQUV2Qyw4QkFBc0IsUUFBUSxDQUFDLFFBQVFBLE1BQUssU0FBUyxHQUFHLENBQUM7QUFDekQsK0JBQXVCLFFBQVEsQ0FBQyxRQUFRQSxNQUFLLFNBQVMsR0FBRyxDQUFDO0FBQzFELFlBQUlBLE1BQUssbUJBQW1CLGFBQWEsTUFBTSxHQUFHO0FBQ2hELHlCQUFlLHdCQUF3QjtBQUFBLFFBQ3pDO0FBQ0EsdUJBQWUsT0FBTyxTQUFTO0FBQUEsTUFDakM7QUFFTyxNQUFNLDJCQUEyQixPQUN0QyxRQUNBLGVBQ0EsUUFDQSxXQUNBLHVCQUNBLE9BQ0EscUJBQXFCLFVBQ0g7QUFDbEIsWUFBSSxDQUFDLFFBQVE7QUFDWCx3QkFBYyxLQUFLLENBQUM7QUFDcEI7QUFBQSxRQUNGO0FBRUEsY0FBTUEsUUFBTyxZQUFZO0FBQ3pCLGNBQU0sVUFBVUEsTUFBSztBQUVyQixjQUFNLFdBQVcsT0FBTyxDQUFDO0FBQ3pCLGNBQU0sT0FBTyxPQUFPLENBQUM7QUFDckIsY0FBTUMsWUFBVyxPQUFPLENBQUM7QUFDekIsWUFBSSxpQkFBaUJBO0FBRXJCLFlBQUk7QUFDSixZQUFJO0FBRUosWUFBSSxhQUFhLGFBQWFBLGNBQWEsZ0JBQWdCQSxjQUFhLGNBQWM7QUFDcEYsZ0JBQU0sSUFBSSxNQUFNLHdDQUF3QztBQUFBLFFBQzFEO0FBRUEsWUFBSSxzQkFBc0JBLGNBQWEsY0FBYztBQUNuRCxnQkFBTSxJQUFJO0FBQUEsWUFDUiwyREFBMkQsS0FBSztBQUFBLFVBQ2xFO0FBQUEsUUFDRjtBQUVBLFlBQUlBLGNBQWEsY0FBYztBQUM3QixnQkFBTSxZQUFZLE9BQU8sQ0FBQyxFQUFFO0FBQzVCLDJCQUFpQiwyQkFBMkIsMkJBQTJCLFFBQVEsR0FBRyxJQUFJO0FBRXRGLGNBQUksT0FBMEI7QUFDNUIsa0JBQU0saUJBQWlCRCxNQUFLO0FBQzVCLGdCQUFJLENBQUMsZ0JBQWdCO0FBQ25CLG9CQUFNLElBQUksTUFBTSxxRUFBcUU7QUFBQSxZQUN2RjtBQUVBLHNCQUFVLGVBQWUsV0FBVyxTQUFTO0FBQUEsVUFDL0MsT0FBTztBQUNMLGtCQUFNLGlCQUFpQkEsTUFBSztBQUM1QixnQkFBSSxDQUFDLGdCQUFnQjtBQUNuQixvQkFBTSxJQUFJLE1BQU0scUVBQXFFO0FBQUEsWUFDdkY7QUFDQSxzQkFBVSxlQUFlLFdBQVcsT0FBTyxXQUFXLGNBQWM7QUFBQSxVQUN0RTtBQUFBLFFBQ0YsV0FBV0MsY0FBYSxhQUFhO0FBQ25DLGdCQUFNLFdBQVcsT0FBTyxDQUFDLEVBQUU7QUFDM0IsMkJBQWlCLDJCQUEyQiwyQkFBMkIsUUFBUSxHQUFHLElBQUk7QUFFdEYsZ0JBQU0sbUJBQW1CRCxNQUFLO0FBQzlCLGNBQUksQ0FBQyxrQkFBa0I7QUFDckIsa0JBQU0sSUFBSSxNQUFNLG1FQUFtRTtBQUFBLFVBQ3JGO0FBQ0Esb0JBQVUsaUJBQWlCLFdBQVcsVUFBVSwyQkFBMkIsUUFBUSxHQUFHLElBQUk7QUFBQSxRQUM1RixPQUFPO0FBQ0wsZ0JBQU0sT0FBTyxPQUFPLENBQUM7QUFFckIsY0FBSSxNQUFNLFFBQVEsSUFBSSxHQUFHO0FBRXZCLDZCQUFpQixVQUFVLEtBQUs7QUFDaEMsc0JBQVVBLE1BQUssUUFBUSxjQUFjO0FBQ3JDLG1CQUFPLEtBQUssT0FBTztBQUNuQixxQkFBUyxJQUFJLEdBQUcsSUFBSSxLQUFLLFFBQVEsS0FBSztBQUNwQyxrQkFBSSxPQUFPLEtBQUssQ0FBQyxNQUFNLFVBQVU7QUFDL0Isc0JBQU0sSUFBSSxVQUFVLHdCQUF3QixDQUFDLGtCQUFrQjtBQUFBLGNBQ2pFO0FBQ0EsY0FBQUEsTUFBSyxTQUFTLFVBQVUsSUFBSSxTQUFTLGdCQUFnQixLQUFLLENBQUMsR0FBRyxNQUFNLEdBQUcsR0FBRztBQUFBLFlBQzVFO0FBQUEsVUFDRixPQUFPO0FBQ0wsa0JBQU0sZUFBZUEsTUFBSztBQUMxQixrQkFBTSxnQkFBZ0JBLE1BQUs7QUFDM0IsZ0JBQUksYUFBYSxZQUFZLGdCQUFnQixlQUFlO0FBQzFELG9CQUFNLGFBQWFBLE1BQUssYUFBYSxxQkFBcUI7QUFFMUQsa0JBQUksYUFBYSxXQUFXLFVBQVUsS0FBSyxjQUFjLFdBQVcsVUFBVSxHQUFHO0FBQy9FLHNCQUFNLGVBQWUsMkJBQTJCLFFBQVE7QUFDeEQsaUNBQWlCLDJCQUEyQixjQUFjLElBQUk7QUFDOUQsaUNBQWlCO0FBQ2pCLHNCQUFNLHdCQUF3QkEsTUFBSztBQUNuQyxzQkFBTSxlQUFlQSxNQUFLO0FBQzFCLG9CQUFJLENBQUMseUJBQXlCLENBQUMsY0FBYztBQUMzQyx3QkFBTSxJQUFJLE1BQU0sbUVBQW1FO0FBQUEsZ0JBQ3JGO0FBQ0Esc0JBQU0sV0FBVyxNQUFNLHNCQUFzQixXQUFXLGNBQWMsSUFBZ0I7QUFDdEYsNkJBQWEsVUFBVSxJQUFJLFdBQVcsS0FBSyxRQUFRLEtBQUssWUFBWSxLQUFLLFVBQVUsQ0FBQztBQUNwRiwwQkFBVTtBQUFBLGNBQ1osT0FBTztBQUNMLGlDQUFpQixLQUFLO0FBQ3RCLDBCQUFVQSxNQUFLLFFBQVEsY0FBYztBQUNyQyx1QkFBTyxLQUFLLE9BQU87QUFDbkIsZ0JBQUFBLE1BQUssT0FBTyxJQUFJLElBQUksV0FBVyxLQUFLLFFBQVEsS0FBSyxZQUFZLGNBQWMsR0FBRyxPQUFPO0FBQUEsY0FDdkY7QUFBQSxZQUNGLE9BQU87QUFDTCwrQkFBaUIsS0FBSztBQUN0Qix3QkFBVUEsTUFBSyxRQUFRLGNBQWM7QUFDckMscUJBQU8sS0FBSyxPQUFPO0FBQ25CLGNBQUFBLE1BQUssT0FBTyxJQUFJLElBQUksV0FBVyxLQUFLLFFBQVEsS0FBSyxZQUFZLGNBQWMsR0FBRyxPQUFPO0FBQUEsWUFDdkY7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUVBLGNBQU0sUUFBUUEsTUFBSyxVQUFVO0FBQzdCLGNBQU0sYUFBYUEsTUFBSyxXQUFXLElBQUksS0FBSyxNQUFNO0FBQ2xELFlBQUk7QUFDRixlQUFLLFFBQVEsQ0FBQyxHQUFHRSxXQUFVRixNQUFLLFNBQVMsYUFBYUUsU0FBUSxTQUFTLEdBQUcsWUFBWSxJQUFJLFFBQVEsS0FBSyxDQUFDO0FBQ3hHLGdCQUFNQyxVQUFTSCxNQUFLO0FBQUEsWUFDbEIsMkJBQTJCLFFBQVE7QUFBQSxZQUNuQztBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUEsWUFDQSxLQUFLO0FBQUEsWUFDTCx5QkFBeUIsY0FBYztBQUFBLFVBQ3pDO0FBQ0EsY0FBSUcsWUFBVyxHQUFHO0FBQ2hCLDJCQUFlLGlEQUFpRCxTQUFTLFdBQVcsS0FBSyxHQUFHO0FBQUEsVUFDOUY7QUFDQSx3QkFBYyxLQUFLQSxPQUFNO0FBQUEsUUFDM0IsVUFBRTtBQUNBLFVBQUFILE1BQUssYUFBYSxLQUFLO0FBQUEsUUFDekI7QUFBQSxNQUNGO0FBS08sTUFBTSxNQUFNLE9BQ2pCLFdBQ0EsY0FDQSxjQUNBLGVBQ0EsZUFDQSxZQUM4QjtBQUM5QixjQUFNQSxRQUFPLFlBQVk7QUFDekIsY0FBTSxVQUFVQSxNQUFLO0FBQ3JCLGNBQU0sVUFBVSxlQUFlLElBQUksU0FBUztBQUM1QyxZQUFJLENBQUMsU0FBUztBQUNaLGdCQUFNLElBQUksTUFBTSw2Q0FBNkMsU0FBUyxFQUFFO0FBQUEsUUFDMUU7QUFDQSxjQUFNLGdCQUFnQixRQUFRLENBQUM7QUFDL0IsY0FBTSx3QkFBd0IsUUFBUSxDQUFDO0FBQ3ZDLGNBQU0seUJBQXlCLFFBQVEsQ0FBQztBQUN4QyxjQUFNLGlCQUFpQixRQUFRLENBQUM7QUFDaEMsY0FBTSxxQkFBcUIsUUFBUSxDQUFDO0FBQ3BDLGNBQU0sbUJBQW1CLFFBQVEsQ0FBQztBQUVsQyxjQUFNLGFBQWEsYUFBYTtBQUNoQyxjQUFNLGNBQWMsY0FBYztBQUVsQyxZQUFJLG1CQUFtQjtBQUN2QixZQUFJLG1CQUE2QixDQUFDO0FBRWxDLGNBQU0scUJBQStCLENBQUM7QUFDdEMsY0FBTSxzQkFBZ0MsQ0FBQztBQUN2QyxjQUFNLG9CQUE4QixDQUFDO0FBRXJDLGNBQU0saUJBQWlCQSxNQUFLLFVBQVU7QUFDdEMsY0FBTSxvQkFBb0JBLE1BQUssV0FBVyxhQUFhLE9BQU87QUFDOUQsY0FBTSxtQkFBbUJBLE1BQUssV0FBVyxhQUFhLE9BQU87QUFDN0QsY0FBTSxxQkFBcUJBLE1BQUssV0FBVyxjQUFjLE9BQU87QUFDaEUsY0FBTSxvQkFBb0JBLE1BQUssV0FBVyxjQUFjLE9BQU87QUFFL0QsWUFBSTtBQUNGLFdBQUMsa0JBQWtCLGdCQUFnQixJQUFJLGNBQWMsT0FBTztBQUc1RCxtQkFBUyxJQUFJLEdBQUcsSUFBSSxZQUFZLEtBQUs7QUFDbkMsa0JBQU07QUFBQSxjQUNKLGFBQWEsQ0FBQztBQUFBLGNBQ2Q7QUFBQSxjQUNBO0FBQUEsY0FDQTtBQUFBLGNBQ0Esc0JBQXNCLGFBQWEsQ0FBQyxDQUFDO0FBQUEsY0FDckMsYUFBYSxDQUFDO0FBQUEsY0FDZDtBQUFBLFlBQ0Y7QUFBQSxVQUNGO0FBR0EsbUJBQVMsSUFBSSxHQUFHLElBQUksYUFBYSxLQUFLO0FBQ3BDLGtCQUFNO0FBQUEsY0FDSixjQUFjLENBQUM7QUFBQSxjQUNmO0FBQUEsY0FDQTtBQUFBLGNBQ0E7QUFBQSxjQUNBLHVCQUF1QixjQUFjLENBQUMsQ0FBQztBQUFBLGNBQ3ZDLGFBQWEsY0FBYyxDQUFDO0FBQUEsY0FDNUI7QUFBQSxZQUNGO0FBQUEsVUFDRjtBQUVBLG1CQUFTLElBQUksR0FBRyxJQUFJLFlBQVksS0FBSztBQUNuQyxZQUFBQSxNQUFLLFNBQVMsb0JBQW9CLElBQUksU0FBUyxtQkFBbUIsQ0FBQyxHQUFHLEdBQUc7QUFDekUsWUFBQUEsTUFBSyxTQUFTLG1CQUFtQixJQUFJLFNBQVMsc0JBQXNCLGFBQWEsQ0FBQyxDQUFDLEdBQUcsR0FBRztBQUFBLFVBQzNGO0FBQ0EsbUJBQVMsSUFBSSxHQUFHLElBQUksYUFBYSxLQUFLO0FBQ3BDLFlBQUFBLE1BQUssU0FBUyxxQkFBcUIsSUFBSSxTQUFTLG9CQUFvQixDQUFDLEdBQUcsR0FBRztBQUMzRSxZQUFBQSxNQUFLLFNBQVMsb0JBQW9CLElBQUksU0FBUyx1QkFBdUIsY0FBYyxDQUFDLENBQUMsR0FBRyxHQUFHO0FBQUEsVUFDOUY7QUFFQSxjQUFnQyxrQkFBa0IsQ0FBQyxrQkFBa0I7QUFDbkUsa0JBQU0sRUFBRSxRQUFRLDBCQUEwQixnQ0FBZ0MsSUFBSTtBQUU5RSxnQkFBSSxzQkFBc0IsV0FBVyxZQUFZO0FBQy9DLG9CQUFNLElBQUk7QUFBQSxnQkFDUiwyQkFBMkIsVUFBVSw0REFBNEQsc0JBQXNCLE1BQU07QUFBQSxjQUMvSDtBQUFBLFlBQ0Y7QUFHQSxxQkFBUyxJQUFJLEdBQUcsSUFBSSxZQUFZLEtBQUs7QUFDbkMsb0JBQU0sUUFBUSxhQUFhLENBQUM7QUFDNUIsb0JBQU1JLGFBQVksTUFBTUosTUFBSyxjQUFjLFFBQVEsc0JBQXNCLEtBQUssR0FBRyxtQkFBbUIsQ0FBQyxDQUFDO0FBQ3RHLGtCQUFJSSxlQUFjLEdBQUc7QUFDbkIsK0JBQWUsb0JBQW9CLENBQUMsaUJBQWlCLFNBQVMsR0FBRztBQUFBLGNBQ25FO0FBQUEsWUFDRjtBQUdBLHFCQUFTLElBQUksR0FBRyxJQUFJLGFBQWEsS0FBSztBQUNwQyxvQkFBTSxRQUFRLGNBQWMsQ0FBQztBQUM3QixvQkFBTUgsWUFBVyxjQUFjLENBQUMsSUFBSSxDQUFDO0FBRXJDLGtCQUFJQSxXQUFVO0FBRVosc0JBQU1HLGFBQVlKLE1BQUssZUFBZSxRQUFRLHVCQUF1QixLQUFLLEdBQUcsb0JBQW9CLENBQUMsR0FBRyxDQUFDO0FBQ3RHLG9CQUFJSSxlQUFjLEdBQUc7QUFDbkIsaUNBQWUsbUNBQW1DLENBQUMsaUJBQWlCLFNBQVMsR0FBRztBQUFBLGdCQUNsRjtBQUFBLGNBQ0YsT0FBTztBQUVMLHNCQUFNQSxhQUFZSixNQUFLO0FBQUEsa0JBQ3JCO0FBQUEsa0JBQ0EsdUJBQXVCLEtBQUs7QUFBQSxrQkFDNUI7QUFBQSxrQkFDQSxnQ0FBZ0MsS0FBSztBQUFBLGdCQUN2QztBQUNBLG9CQUFJSSxlQUFjLEdBQUc7QUFDbkIsaUNBQWUscUJBQXFCLENBQUMsUUFBUSx5QkFBeUIsQ0FBQyxDQUFDLGdCQUFnQixTQUFTLEdBQUc7QUFBQSxnQkFDdEc7QUFBQSxjQUNGO0FBQUEsWUFDRjtBQUNBLDJCQUFlLElBQUksV0FBVztBQUFBLGNBQzVCO0FBQUEsY0FDQTtBQUFBLGNBQ0E7QUFBQSxjQUNBO0FBQUEsY0FDQTtBQUFBLGNBQ0E7QUFBQSxZQUNGLENBQUM7QUFBQSxVQUNIO0FBRUEsVUFBQUosTUFBSyxpQkFBaUIsYUFBYTtBQUNuQyxVQUFBQSxNQUFLLGtCQUFrQixhQUFhO0FBRXBDLGNBQUk7QUFDSixjQUFnQyxnQkFBZ0I7QUFDOUMsd0JBQVksTUFBTUEsTUFBSztBQUFBLGNBQ3JCO0FBQUEsY0FDQSxlQUFlO0FBQUEsY0FDZjtBQUFBLGNBQ0E7QUFBQSxjQUNBO0FBQUEsWUFDRjtBQUFBLFVBQ0YsT0FBTztBQUNMLHdCQUFZLE1BQU1BLE1BQUs7QUFBQSxjQUNyQjtBQUFBLGNBQ0E7QUFBQSxjQUNBO0FBQUEsY0FDQTtBQUFBLGNBQ0E7QUFBQSxjQUNBO0FBQUEsY0FDQTtBQUFBLGNBQ0E7QUFBQSxZQUNGO0FBQUEsVUFDRjtBQUVBLGNBQUksY0FBYyxHQUFHO0FBQ25CLDJCQUFlLDBCQUEwQjtBQUFBLFVBQzNDO0FBRUEsZ0JBQU0sU0FBMkIsQ0FBQztBQUNsQyxnQkFBTSxpQkFBNEQsQ0FBQztBQUVuRSxtQkFBUyxJQUFJLEdBQUcsSUFBSSxhQUFhLEtBQUs7QUFDcEMsa0JBQU0sU0FBUyxPQUFPQSxNQUFLLFNBQVMscUJBQXFCLElBQUksU0FBUyxHQUFHLENBQUM7QUFDMUUsZ0JBQUksV0FBVyxvQkFBb0IsQ0FBQyxHQUFHO0FBRXJDLHFCQUFPLEtBQUssY0FBYyxDQUFDLENBQUU7QUFDN0I7QUFBQSxZQUNGO0FBRUEsa0JBQU0sMkJBQTJCQSxNQUFLLFVBQVU7QUFFaEQsa0JBQU0sbUJBQW1CQSxNQUFLLFdBQVcsSUFBSSxPQUFPO0FBRXBELGdCQUFJLG1CQUFtQjtBQUN2QixnQkFBSSxNQUNGLGFBQWE7QUFDZixnQkFBSTtBQUNGLG9CQUFNSSxhQUFZSixNQUFLO0FBQUEsZ0JBQ3JCO0FBQUEsZ0JBQ0E7QUFBQSxnQkFDQSxtQkFBbUI7QUFBQSxnQkFDbkIsbUJBQW1CLElBQUk7QUFBQSxnQkFFdkIsbUJBQW1CLElBQUk7QUFBQSxjQUN6QjtBQUNBLGtCQUFJSSxlQUFjLEdBQUc7QUFDbkIsK0JBQWUsNENBQTRDLENBQUMsR0FBRztBQUFBLGNBQ2pFO0FBQ0Esb0JBQU0sWUFBWSxZQUFZLElBQUksUUFBUTtBQUMxQyxvQkFBTSxXQUFXLE9BQU9KLE1BQUssU0FBUyxrQkFBa0IsU0FBUyxDQUFDO0FBQ2xFLDJCQUFhQSxNQUFLLFNBQVMsbUJBQW1CLFNBQVMsR0FBRztBQUMxRCxvQkFBTSxhQUFhQSxNQUFLLFNBQVMsbUJBQW1CLFVBQVUsR0FBRyxHQUFHO0FBQ3BFLG9CQUFNLGFBQWEsT0FBT0EsTUFBSyxTQUFTLG1CQUFtQixVQUFVLEdBQUcsU0FBUyxDQUFDO0FBQ2xGLG9CQUFNLE9BQU8sQ0FBQztBQUNkLHVCQUFTSyxLQUFJLEdBQUdBLEtBQUksWUFBWUEsTUFBSztBQUNuQyxxQkFBSyxLQUFLLE9BQU9MLE1BQUssU0FBUyxhQUFhSyxLQUFJLFNBQVMsU0FBUyxDQUFDLENBQUM7QUFBQSxjQUN0RTtBQUNBLGtCQUFJTCxNQUFLLFNBQVMsVUFBVSxNQUFNLEdBQUc7QUFDbkMsK0JBQWUsb0NBQW9DO0FBQUEsY0FDckQ7QUFDQSxvQkFBTSxPQUFPLEtBQUssT0FBTyxDQUFDLEdBQUcsTUFBTSxJQUFJLEdBQUcsQ0FBQztBQUMzQyxxQkFBTywyQkFBMkIsUUFBUTtBQUUxQyxvQkFBTSxvQkFBb0IsZ0JBQWdCLHlCQUF5QixjQUFjLENBQUMsQ0FBQztBQUVuRixrQkFBSSxTQUFTLFVBQVU7QUFDckIsb0JBQUksc0JBQXNCLGdCQUFnQixzQkFBc0IsYUFBYTtBQUMzRSx3QkFBTSxJQUFJLE1BQU0sd0NBQXdDO0FBQUEsZ0JBQzFEO0FBQ0Esc0JBQU0sYUFBdUIsQ0FBQztBQUM5Qix5QkFBU0ssS0FBSSxHQUFHQSxLQUFJLE1BQU1BLE1BQUs7QUFDN0Isd0JBQU0sU0FBU0wsTUFBSyxTQUFTLGFBQWFLLEtBQUksU0FBUyxHQUFHO0FBQzFELHdCQUFNLGFBQWFMLE1BQUssU0FBUyxjQUFjSyxLQUFJLEtBQUssU0FBUyxHQUFHO0FBQ3BFLHdCQUFNLGlCQUFpQkEsT0FBTSxPQUFPLElBQUksU0FBWSxhQUFhO0FBQ2pFLDZCQUFXLEtBQUtMLE1BQUssYUFBYSxRQUFRLGNBQWMsQ0FBQztBQUFBLGdCQUMzRDtBQUNBLHVCQUFPLEtBQUssQ0FBQyxNQUFNLE1BQU0sWUFBWSxLQUFLLENBQUM7QUFBQSxjQUM3QyxPQUFPO0FBR0wsb0JBQUksc0JBQXNCLGdCQUFnQixPQUFPLEdBQUc7QUFDbEQsd0JBQU0sWUFBWSxRQUEyQkEsTUFBSyxrQkFBa0JBLE1BQUs7QUFDekUsc0JBQUksQ0FBQyxXQUFXO0FBQ2QsMEJBQU0sSUFBSSxNQUFNLHVFQUF1RTtBQUFBLGtCQUN6RjtBQUNBLHdCQUFNLFlBQVksVUFBVSxVQUFVO0FBQ3RDLHdCQUFNLGFBQWEsMkJBQTJCLFVBQVUsSUFBSTtBQUM1RCxzQkFBSSxlQUFlLFVBQWEsQ0FBQyx5QkFBeUIsSUFBSSxHQUFHO0FBQy9ELDBCQUFNLElBQUksTUFBTSwwQkFBMEIsSUFBSSxFQUFFO0FBQUEsa0JBQ2xEO0FBR0EscUNBQW1CO0FBRW5CLHNCQUFJLE9BQTBCO0FBQzVCLG9CQUFBQSxNQUFLLHFCQUFzQixXQUFXLFdBQVcsVUFBVTtBQUMzRCwwQkFBTSx1QkFBdUJBLE1BQUssdUJBQXdCLFdBQVcsWUFBWSxTQUFTO0FBQzFGLDJCQUFPLEtBQUs7QUFBQSxzQkFDVjtBQUFBLHNCQUNBO0FBQUEsc0JBQ0E7QUFBQSx3QkFDRTtBQUFBLHdCQUNBLFVBQVUsWUFBWTtBQUNwQixnQ0FBTSxjQUFjLE1BQU0scUJBQXFCO0FBQy9DLGdDQUFNLE9BQU8sS0FBSyxrQ0FBa0MsSUFBSyxHQUFHLFdBQVc7QUFDdkUsaUNBQU87QUFBQSx3QkFDVDtBQUFBLHdCQUNBLFNBQVMsTUFBTTtBQUNiLDhCQUFJQSxNQUFLLGtCQUFrQixNQUFNLE1BQU0sR0FBRztBQUN4QywyQ0FBZSx1QkFBdUI7QUFBQSwwQkFDeEM7QUFBQSx3QkFDRjtBQUFBLHNCQUNGO0FBQUEsc0JBQ0E7QUFBQSxvQkFDRixDQUFDO0FBQUEsa0JBQ0gsT0FBTztBQUNMLDJCQUFPLEtBQUs7QUFBQSxzQkFDVjtBQUFBLHNCQUNBO0FBQUEsc0JBQ0E7QUFBQSx3QkFDRTtBQUFBLHdCQUNBLFVBQVVBLE1BQUsscUJBQXNCLFdBQVcsWUFBWSxJQUFJO0FBQUEsd0JBQ2hFLFNBQVMsTUFBTTtBQUNiLDhCQUFJQSxNQUFLLGtCQUFrQixNQUFNLE1BQU0sR0FBRztBQUN4QywyQ0FBZSx1QkFBdUI7QUFBQSwwQkFDeEM7QUFBQSx3QkFDRjtBQUFBLHNCQUNGO0FBQUEsc0JBQ0E7QUFBQSxvQkFDRixDQUFDO0FBQUEsa0JBQ0g7QUFBQSxnQkFDRixXQUFXLHNCQUFzQixlQUFlLE9BQU8sR0FBRztBQUN4RCx3QkFBTSxlQUFlQSxNQUFLO0FBQzFCLHdCQUFNLGtDQUFrQ0EsTUFBSztBQUM3QyxzQkFBSSxDQUFDLGdCQUFnQixDQUFDLGlDQUFpQztBQUNyRCwwQkFBTSxJQUFJLE1BQU0scUVBQXFFO0FBQUEsa0JBQ3ZGO0FBQ0Esd0JBQU0sYUFBYSwyQkFBMkIsVUFBVSxJQUFJO0FBQzVELHNCQUFJLGVBQWUsVUFBYSxDQUFDLHdCQUF3QixJQUFJLEdBQUc7QUFDOUQsMEJBQU0sSUFBSSxNQUFNLDBCQUEwQixJQUFJLEVBQUU7QUFBQSxrQkFDbEQ7QUFDQSxzQkFBSSxDQUFDLGdDQUFnQyxXQUFXLE1BQU0sS0FBSyxHQUFHO0FBQzVELDBCQUFNLElBQUk7QUFBQSxzQkFDUixxQ0FBcUMsSUFBSTtBQUFBLG9CQUMzQztBQUFBLGtCQUNGO0FBS0Esd0JBQU0sV0FBVyxNQUFNLGFBQWEsV0FBVyxZQUFZLFVBQVUsTUFBTSxLQUFLO0FBR2hGLHFDQUFtQjtBQUVuQix5QkFBTyxLQUFLO0FBQUEsb0JBQ1Y7QUFBQSxvQkFDQTtBQUFBLG9CQUNBO0FBQUEsc0JBQ0U7QUFBQSxzQkFDQSxVQUFVQSxNQUFLLDhCQUErQixZQUFZLElBQUk7QUFBQSxzQkFDOUQsU0FBUyxNQUFNO0FBQ2Isd0JBQUFBLE1BQUsscUJBQXNCLFVBQVU7QUFDckMsd0JBQUFBLE1BQUssa0JBQWtCLE1BQU07QUFBQSxzQkFDL0I7QUFBQSxvQkFDRjtBQUFBLG9CQUNBO0FBQUEsa0JBQ0YsQ0FBQztBQUFBLGdCQUNILFdBQVcsc0JBQXNCLDBCQUEwQixPQUFPLEdBQUc7QUFDbkUsd0JBQU0sT0FBT0EsTUFBSyw4QkFBK0IsWUFBWSxJQUFnQyxFQUFFO0FBQy9GLHdCQUFNLFFBQVEsT0FBTztBQUVyQixxQ0FBbUI7QUFDbkIsaUNBQWU7QUFBQSxxQkFDWixZQUFZO0FBQ1gsNEJBQU0sU0FBb0MsQ0FBQyxPQUFPLE1BQU0sSUFBSTtBQUM1RCxzQkFBQUEsTUFBSyxxQkFBc0IsVUFBVTtBQUNyQyxzQkFBQUEsTUFBSyxrQkFBa0IsTUFBTTtBQUM3Qiw2QkFBTztBQUFBLG9CQUNULEdBQUc7QUFBQSxrQkFDTDtBQUNBLHlCQUFPLEtBQUssQ0FBQyxNQUFNLE1BQU0sQ0FBQyxHQUFHLEtBQUssQ0FBQztBQUFBLGdCQUNyQyxPQUFPO0FBQ0wsd0JBQU0sd0JBQXdCLGtDQUFrQyxJQUFJO0FBQ3BFLHdCQUFNLE9BQU8sSUFBSSxzQkFBc0IsSUFBSTtBQUMzQyxzQkFBSSxXQUFXLEtBQUssUUFBUSxLQUFLLFlBQVksS0FBSyxVQUFVLEVBQUU7QUFBQSxvQkFDNURBLE1BQUssT0FBTyxTQUFTLFlBQVksYUFBYSxLQUFLLFVBQVU7QUFBQSxrQkFDL0Q7QUFDQSx5QkFBTyxLQUFLLENBQUMsTUFBTSxNQUFNLE1BQU0sS0FBSyxDQUFDO0FBQUEsZ0JBQ3ZDO0FBQUEsY0FDRjtBQUFBLFlBQ0YsVUFBRTtBQUNBLGNBQUFBLE1BQUssYUFBYSx3QkFBd0I7QUFDMUMsa0JBQUksU0FBUyxZQUFZLFlBQVk7QUFDbkMsZ0JBQUFBLE1BQUssTUFBTSxVQUFVO0FBQUEsY0FDdkI7QUFDQSxrQkFBSSxDQUFDLGtCQUFrQjtBQUNyQixnQkFBQUEsTUFBSyxrQkFBa0IsTUFBTTtBQUFBLGNBQy9CO0FBQUEsWUFDRjtBQUFBLFVBQ0Y7QUFFQSxjQUFJLGtCQUFrQixDQUFDLG9CQUFvQjtBQUN6QyxnQkFBSUEsTUFBSyxzQkFBc0IsZUFBZSxNQUFNLE1BQU0sR0FBRztBQUMzRCw2QkFBZSw0QkFBNEI7QUFBQSxZQUM3QztBQUNBLDJCQUFlLElBQUksV0FBVztBQUFBLGNBQzVCO0FBQUEsY0FDQTtBQUFBLGNBQ0E7QUFBQSxjQUNBO0FBQUEsY0FDQTtBQUFBLGNBQ0E7QUFBQSxZQUNGLENBQUM7QUFBQSxVQUNIO0FBRUEscUJBQVcsQ0FBQyxPQUFPLElBQUksS0FBSyxNQUFNLFFBQVEsSUFBSSxjQUFjLEdBQUc7QUFDN0QsbUJBQU8sS0FBSyxFQUFFLENBQUMsSUFBSTtBQUFBLFVBQ3JCO0FBQ0EsaUJBQU87QUFBQSxRQUNULFVBQUU7QUFDQSxVQUFBQSxNQUFLLGdCQUFnQixhQUFhO0FBRWxDLFVBQUFBLE1BQUssYUFBYSxjQUFjO0FBRWhDLGNBQUksT0FBMEI7QUFDNUIseUJBQWEsUUFBUSxDQUFDLE1BQU07QUFDMUIsa0JBQUksS0FBSyxFQUFFLENBQUMsTUFBTSxjQUFjO0FBQzlCLGdCQUFBQSxNQUFLLHVCQUF3QixFQUFFLENBQUMsRUFBRSxTQUFTO0FBQUEsY0FDN0M7QUFBQSxZQUNGLENBQUM7QUFDRCwwQkFBYyxRQUFRLENBQUMsTUFBTTtBQUMzQixrQkFBSSxLQUFLLEVBQUUsQ0FBQyxNQUFNLGNBQWM7QUFDOUIsZ0JBQUFBLE1BQUssdUJBQXdCLEVBQUUsQ0FBQyxFQUFFLFNBQVM7QUFBQSxjQUM3QztBQUFBLFlBQ0YsQ0FBQztBQUFBLFVBQ0g7QUFDQSw2QkFBbUIsUUFBUSxDQUFDLE1BQU1BLE1BQUssa0JBQWtCLENBQUMsQ0FBQztBQUMzRCw4QkFBb0IsUUFBUSxDQUFDLE1BQU1BLE1BQUssa0JBQWtCLENBQUMsQ0FBQztBQUM1RCw0QkFBa0IsUUFBUSxDQUFDLE1BQU1BLE1BQUssTUFBTSxDQUFDLENBQUM7QUFFOUMsY0FBSSxxQkFBcUIsR0FBRztBQUMxQixZQUFBQSxNQUFLLHNCQUFzQixnQkFBZ0I7QUFBQSxVQUM3QztBQUNBLDJCQUFpQixRQUFRLENBQUMsTUFBTUEsTUFBSyxNQUFNLENBQUMsQ0FBQztBQUFBLFFBQy9DO0FBQUEsTUFDRjtBQUtPLE1BQU0sZUFBZSxDQUFDLGNBQTRCO0FBQ3ZELGNBQU1BLFFBQU8sWUFBWTtBQUN6QixjQUFNLFVBQVUsZUFBZSxJQUFJLFNBQVM7QUFDNUMsWUFBSSxDQUFDLFNBQVM7QUFDWixnQkFBTSxJQUFJLE1BQU0sb0JBQW9CO0FBQUEsUUFDdEM7QUFDQSxjQUFNLGdCQUFnQixRQUFRLENBQUM7QUFHL0IsY0FBTSxrQkFBa0JBLE1BQUssaUJBQWlCLGFBQWE7QUFDM0QsWUFBSSxvQkFBb0IsR0FBRztBQUN6Qix5QkFBZSxpQ0FBaUM7QUFBQSxRQUNsRDtBQUNBLFFBQUFBLE1BQUssU0FBUyxlQUFlO0FBQUEsTUFDL0I7QUFFTyxNQUFNLDZCQUE2QixDQUFDLFlBQXNFO0FBQy9HLGNBQU0sVUFBNkIsQ0FBQztBQUNwQyxtQkFBVyxVQUFVLFNBQVM7QUFDNUIsZ0JBQU0sT0FBTyxPQUFPLENBQUM7QUFDckIsY0FBSSxDQUFDLE1BQU0sUUFBUSxJQUFJLEtBQUssWUFBWSxNQUFNO0FBQzVDLG9CQUFRLEtBQUssS0FBSyxNQUFNO0FBQUEsVUFDMUI7QUFBQSxRQUNGO0FBQ0EsZUFBTztBQUFBLE1BQ1Q7QUFBQTtBQUFBOzs7QUMvakNBLE1Bb0JNLFNBQ0YsYUFDQU0sZUFDQUMsY0FDQUMsVUFDQSxvQkFHQSxtQkFDRSxpQkFFQSxrQkFTQSxjQU1BLHNCQWtDTyxvQ0ErRUEsaUJBYUFDLHlCQWFBQyxnQkF3QkFDLGlCQWFBQyxNQWdDQUM7QUE5UGI7QUFBQTtBQUFBO0FBR0E7QUFTQTtBQUNBO0FBQ0E7QUFNQSxNQUFNLFVBQVUsTUFBZSxDQUFDLENBQUNDLEtBQUksS0FBSyxTQUFTLE9BQU8sYUFBYTtBQUV2RSxNQUFJUixnQkFBZTtBQUNuQixNQUFJQyxlQUFjO0FBQ2xCLE1BQUlDLFdBQVU7QUFLZCxNQUFNLGtCQUFpRixvQkFBSSxJQUFJO0FBRS9GLE1BQU0sbUJBQW1CLENBQUMsTUFBOEIsY0FBK0M7QUFDckcsY0FBTSxRQUFRLGdCQUFnQixJQUFJLElBQUk7QUFDdEMsWUFBSSxPQUFPO0FBQ1QsZ0JBQU0sS0FBSyxTQUFTO0FBQUEsUUFDdEIsT0FBTztBQUNMLDBCQUFnQixJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUM7QUFBQSxRQUN2QztBQUFBLE1BQ0Y7QUFFQSxNQUFNLGVBQWUsTUFBWTtBQUMvQixZQUFJRixpQkFBZ0IsQ0FBQ0MsZ0JBQWVDLFlBQVcsQ0FBQyxhQUFhO0FBQzNELGdCQUFNLElBQUksTUFBTSxrQkFBa0I7QUFBQSxRQUNwQztBQUFBLE1BQ0Y7QUFFQSxNQUFNLHVCQUF1QixDQUFDLE9BQTJDO0FBQ3ZFLGdCQUFRLEdBQUcsS0FBSyxNQUFNO0FBQUEsVUFDcEIsS0FBSztBQUNILFlBQUFGLGdCQUFlO0FBQ2YsZ0JBQUksR0FBRyxLQUFLLEtBQUs7QUFDZixjQUFBRSxXQUFVO0FBQ1YsZ0NBQWtCLENBQUMsRUFBRSxHQUFHLEtBQUssR0FBRztBQUFBLFlBQ2xDLE9BQU87QUFDTCxjQUFBRCxlQUFjO0FBQ2QsZ0NBQWtCLENBQUMsRUFBRTtBQUFBLFlBQ3ZCO0FBQ0EsZ0JBQUksb0JBQW9CO0FBQ3RCLGtCQUFJLGdCQUFnQixrQkFBa0I7QUFDdEMsbUNBQXFCO0FBQUEsWUFDdkI7QUFDQTtBQUFBLFVBQ0YsS0FBSztBQUFBLFVBQ0wsS0FBSztBQUFBLFVBQ0wsS0FBSztBQUFBLFVBQ0wsS0FBSztBQUFBLFVBQ0wsS0FBSztBQUFBLFVBQ0wsS0FBSyxpQkFBaUI7QUFDcEIsa0JBQU0sWUFBWSxnQkFBZ0IsSUFBSSxHQUFHLEtBQUssSUFBSTtBQUNsRCxnQkFBSSxHQUFHLEtBQUssS0FBSztBQUNmLHdCQUFVLE1BQU0sRUFBRyxDQUFDLEVBQUUsR0FBRyxLQUFLLEdBQUc7QUFBQSxZQUNuQyxPQUFPO0FBQ0wsd0JBQVUsTUFBTSxFQUFHLENBQUMsRUFBRSxHQUFHLEtBQUssR0FBSTtBQUFBLFlBQ3BDO0FBQ0E7QUFBQSxVQUNGO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxxQ0FBcUMsWUFBMkI7QUFDM0UsWUFBSUEsY0FBYTtBQUNmO0FBQUEsUUFDRjtBQUNBLFlBQUlELGVBQWM7QUFDaEIsZ0JBQU0sSUFBSSxNQUFNLDBDQUEwQztBQUFBLFFBQzVEO0FBQ0EsWUFBSUUsVUFBUztBQUNYLGdCQUFNLElBQUksTUFBTSx1Q0FBdUM7QUFBQSxRQUN6RDtBQUVBLFFBQUFGLGdCQUFlO0FBRWYsWUFBc0MsUUFBUSxHQUFHO0FBQy9DLGlCQUFPLElBQUksUUFBYyxDQUFDLFNBQVMsV0FBVztBQUM1Qyx5QkFBYSxVQUFVO0FBRXZCLGlCQUFLLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxDQUFDLFdBQVcsTUFBTSxNQUFNO0FBQ3JELGtCQUFJO0FBQ0YsOEJBQWM7QUFDZCw0QkFBWSxVQUFVLENBQUMsT0FBbUIsT0FBTyxFQUFFO0FBQ25ELDRCQUFZLFlBQVk7QUFDeEIsb0NBQW9CLENBQUMsU0FBUyxNQUFNO0FBQ3BDLHNCQUFNLFVBQTBCLEVBQUUsTUFBTSxhQUFhLElBQUlRLEtBQUk7QUFNN0Qsb0JBQXlDLENBQUMsUUFBUSxHQUFJLEtBQUssYUFBYSxXQUFXO0FBR2pGLHdCQUFNLHlCQUF5QixpQ0FBaUM7QUFDaEUsc0JBQUksd0JBQXdCO0FBQzFCLDRCQUFRLEdBQUksS0FBSyxZQUFZO0FBQUEsa0JBQy9CO0FBQUEsZ0JBQ0Y7QUFFQSxvQkFDRSxPQUlBO0FBU0EsMEJBQVEsR0FBSSxLQUFLLFlBQVk7QUFBQSxvQkFDM0IsTUFBTSxPQUNGLElBQUksSUFBSSxvQ0FBb0MsTUFBOEIsRUFBRSxPQUM1RSxJQUFJLElBQUksK0JBQStCLE1BQThCLEVBQUU7QUFBQSxrQkFDN0U7QUFBQSxnQkFDRjtBQUNBLDRCQUFZLFlBQVksT0FBTztBQUMvQixxQ0FBcUI7QUFBQSxjQUN2QixTQUFTLEdBQUc7QUFDVix1QkFBTyxDQUFDO0FBQUEsY0FDVjtBQUFBLFlBQ0YsR0FBRyxNQUFNO0FBQUEsVUFDWCxDQUFDO0FBQUEsUUFDSCxPQUFPO0FBQ0wsY0FBSTtBQUNGLGtCQUFNLHNCQUFzQkEsS0FBSSxJQUFJO0FBQ3BDLGtCQUFXLFlBQVlBLElBQUc7QUFDMUIsWUFBQVAsZUFBYztBQUFBLFVBQ2hCLFNBQVMsR0FBRztBQUNWLFlBQUFDLFdBQVU7QUFDVixrQkFBTTtBQUFBLFVBQ1IsVUFBRTtBQUNBLFlBQUFGLGdCQUFlO0FBQUEsVUFDakI7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVPLE1BQU0sa0JBQWtCLE9BQU8sV0FBa0M7QUFDdEUsWUFBc0MsUUFBUSxHQUFHO0FBQy9DLHVCQUFhO0FBQ2IsaUJBQU8sSUFBSSxRQUFjLENBQUMsU0FBUyxXQUFXO0FBQzVDLDZCQUFpQixXQUFXLENBQUMsU0FBUyxNQUFNLENBQUM7QUFDN0Msa0JBQU0sVUFBMEIsRUFBRSxNQUFNLFdBQVcsSUFBSSxFQUFFLFFBQVEsS0FBQVEsS0FBSSxFQUFFO0FBQ3ZFLHdCQUFhLFlBQVksT0FBTztBQUFBLFVBQ2xDLENBQUM7QUFBQSxRQUNILE9BQU87QUFDTCxnQkFBVyxPQUFPQSxNQUFLLE1BQU07QUFBQSxRQUMvQjtBQUFBLE1BQ0Y7QUFFTyxNQUFNTCwwQkFBeUIsT0FBTyxXQUE0RDtBQUN2RyxZQUFzQyxRQUFRLEdBQUc7QUFDL0MsdUJBQWE7QUFDYixpQkFBTyxJQUFJLFFBQW9DLENBQUMsU0FBUyxXQUFXO0FBQ2xFLDZCQUFpQixhQUFhLENBQUMsU0FBUyxNQUFNLENBQUM7QUFDL0Msa0JBQU0sVUFBMEIsRUFBRSxNQUFNLGFBQWEsSUFBSSxFQUFFLE9BQU8sRUFBRTtBQUNwRSx3QkFBYSxZQUFZLFNBQVMsQ0FBQyxPQUFPLE1BQU0sQ0FBQztBQUFBLFVBQ25ELENBQUM7QUFBQSxRQUNILE9BQU87QUFDTCxpQkFBWSx1QkFBdUIsTUFBTTtBQUFBLFFBQzNDO0FBQUEsTUFDRjtBQUVPLE1BQU1DLGlCQUFnQixPQUMzQixPQUNBLFlBQ3lDO0FBQ3pDLFlBQXNDLFFBQVEsR0FBRztBQUUvQyxjQUFJLFNBQVMseUJBQXlCO0FBQ3BDLGtCQUFNLElBQUksTUFBTSxzRUFBc0U7QUFBQSxVQUN4RjtBQUNBLHVCQUFhO0FBQ2IsaUJBQU8sSUFBSSxRQUFxQyxDQUFDLFNBQVMsV0FBVztBQUNuRSw2QkFBaUIsVUFBVSxDQUFDLFNBQVMsTUFBTSxDQUFDO0FBQzVDLGtCQUFNLFVBQTBCLEVBQUUsTUFBTSxVQUFVLElBQUksRUFBRSxPQUFPLFNBQVMsRUFBRSxHQUFHLFFBQVEsRUFBRSxFQUFFO0FBQ3pGLGtCQUFNLGVBQStCLENBQUM7QUFDdEMsZ0JBQUksaUJBQWlCLFlBQVk7QUFDL0IsMkJBQWEsS0FBSyxNQUFNLE1BQU07QUFBQSxZQUNoQztBQUNBLHdCQUFhLFlBQVksU0FBUyxZQUFZO0FBQUEsVUFDaEQsQ0FBQztBQUFBLFFBQ0gsT0FBTztBQUNMLGlCQUFZLGNBQWMsT0FBTyxPQUFPO0FBQUEsUUFDMUM7QUFBQSxNQUNGO0FBRU8sTUFBTUMsa0JBQWlCLE9BQU8sY0FBcUM7QUFDeEUsWUFBc0MsUUFBUSxHQUFHO0FBQy9DLHVCQUFhO0FBQ2IsaUJBQU8sSUFBSSxRQUFjLENBQUMsU0FBUyxXQUFXO0FBQzVDLDZCQUFpQixXQUFXLENBQUMsU0FBUyxNQUFNLENBQUM7QUFDN0Msa0JBQU0sVUFBMEIsRUFBRSxNQUFNLFdBQVcsSUFBSSxVQUFVO0FBQ2pFLHdCQUFhLFlBQVksT0FBTztBQUFBLFVBQ2xDLENBQUM7QUFBQSxRQUNILE9BQU87QUFDTCxVQUFLLGVBQWUsU0FBUztBQUFBLFFBQy9CO0FBQUEsTUFDRjtBQUVPLE1BQU1DLE9BQU0sT0FDakIsV0FDQSxjQUNBLFFBQ0EsZUFDQSxTQUNBLFlBQzhCO0FBQzlCLFlBQXNDLFFBQVEsR0FBRztBQUUvQyxjQUFJLE9BQU8sS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLE1BQU0sS0FBSyxHQUFHO0FBQ3RDLGtCQUFNLElBQUksTUFBTSxpREFBaUQ7QUFBQSxVQUNuRTtBQUVBLGNBQUksUUFBUSxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUc7QUFDMUIsa0JBQU0sSUFBSSxNQUFNLHlEQUF5RDtBQUFBLFVBQzNFO0FBQ0EsdUJBQWE7QUFDYixpQkFBTyxJQUFJLFFBQXNDLENBQUMsU0FBUyxXQUFXO0FBQ3BFLDZCQUFpQixPQUFPLENBQUMsU0FBUyxNQUFNLENBQUM7QUFDekMsa0JBQU0scUJBQXFCO0FBQzNCLGtCQUFNLFVBQTBCO0FBQUEsY0FDOUIsTUFBTTtBQUFBLGNBQ04sSUFBSSxFQUFFLFdBQVcsY0FBYyxRQUFRLG9CQUFvQixlQUFlLFFBQVE7QUFBQSxZQUNwRjtBQUNBLHdCQUFhLFlBQVksU0FBYywyQkFBMkIsa0JBQWtCLENBQUM7QUFBQSxVQUN2RixDQUFDO0FBQUEsUUFDSCxPQUFPO0FBQ0wsaUJBQVksSUFBSSxXQUFXLGNBQWMsUUFBUSxlQUFlLFNBQVMsT0FBTztBQUFBLFFBQ2xGO0FBQUEsTUFDRjtBQUVPLE1BQU1DLGdCQUFlLE9BQU8sY0FBcUM7QUFDdEUsWUFBc0MsUUFBUSxHQUFHO0FBQy9DLHVCQUFhO0FBQ2IsaUJBQU8sSUFBSSxRQUFjLENBQUMsU0FBUyxXQUFXO0FBQzVDLDZCQUFpQixpQkFBaUIsQ0FBQyxTQUFTLE1BQU0sQ0FBQztBQUNuRCxrQkFBTSxVQUEwQixFQUFFLE1BQU0saUJBQWlCLElBQUksVUFBVTtBQUN2RSx3QkFBYSxZQUFZLE9BQU87QUFBQSxVQUNsQyxDQUFDO0FBQUEsUUFDSCxPQUFPO0FBQ0wsVUFBSyxhQUFhLFNBQVM7QUFBQSxRQUM3QjtBQUFBLE1BQ0Y7QUFBQTtBQUFBOzs7QUN6UUEsTUFrQmEsc0JBYUEsc0JBeUJBO0FBeERiO0FBQUE7QUFBQTtBQUdBO0FBVUE7QUFDQTtBQUNBO0FBQ0E7QUFFTyxNQUFNLHVCQUF1QixDQUFDLFFBQWdCLFlBQTBDO0FBQzdGLGdCQUFRLE9BQU8sVUFBVTtBQUFBLFVBQ3ZCLEtBQUs7QUFDSCxtQkFBTyxDQUFDLE9BQU8sTUFBTSxPQUFPLE1BQU0sT0FBTyxNQUFNLEtBQUs7QUFBQSxVQUN0RCxLQUFLO0FBQ0gsbUJBQU8sQ0FBQyxPQUFPLE1BQU0sT0FBTyxNQUFNLEVBQUUsV0FBVyxPQUFPLFVBQVUsR0FBRyxZQUFZO0FBQUEsVUFDakYsS0FBSztBQUNILG1CQUFPLENBQUMsT0FBTyxNQUFNLE9BQU8sTUFBTSxFQUFFLFVBQVUsT0FBTyxTQUFTLEdBQUcsV0FBVztBQUFBLFVBQzlFO0FBQ0Usa0JBQU0sSUFBSSxNQUFNLDBCQUEwQixPQUFPLFFBQVEsUUFBUSxRQUFRLENBQUMsRUFBRTtBQUFBLFFBQ2hGO0FBQUEsTUFDRjtBQUVPLE1BQU0sdUJBQXVCLENBQUMsV0FBbUM7QUFDdEUsZ0JBQVEsT0FBTyxDQUFDLEdBQUc7QUFBQSxVQUNqQixLQUFLO0FBQ0gsbUJBQU8sSUFBSUUsUUFBTyxPQUFPLENBQUMsR0FBRyxPQUFPLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQztBQUFBLFVBQ25ELEtBQUssY0FBYztBQUNqQixrQkFBTSxXQUFXLE9BQU8sQ0FBQztBQUN6QixnQkFBSSxDQUFDLHlCQUF5QixRQUFRLEdBQUc7QUFDdkMsb0JBQU0sSUFBSSxNQUFNLDRCQUE0QixRQUFRLCtCQUErQjtBQUFBLFlBQ3JGO0FBQ0Esa0JBQU0sRUFBRSxXQUFXLFVBQVUsUUFBUSxJQUFJLE9BQU8sQ0FBQztBQUNqRCxtQkFBT0EsUUFBTyxjQUFjLFdBQVcsRUFBRSxVQUFVLE1BQU0sT0FBTyxDQUFDLEdBQUcsVUFBVSxRQUFRLENBQUM7QUFBQSxVQUN6RjtBQUFBLFVBQ0EsS0FBSyxhQUFhO0FBQ2hCLGtCQUFNLFdBQVcsT0FBTyxDQUFDO0FBQ3pCLGdCQUFJLENBQUMsd0JBQXdCLFFBQVEsR0FBRztBQUN0QyxvQkFBTSxJQUFJLE1BQU0sNEJBQTRCLFFBQVEsb0NBQW9DO0FBQUEsWUFDMUY7QUFDQSxrQkFBTSxFQUFFLFVBQVUsVUFBVSxRQUFRLElBQUksT0FBTyxDQUFDO0FBQ2hELG1CQUFPQSxRQUFPLGFBQWEsVUFBVSxFQUFFLFVBQVUsTUFBTSxPQUFPLENBQUMsR0FBRyxVQUFVLFFBQVEsQ0FBQztBQUFBLFVBQ3ZGO0FBQUEsVUFDQTtBQUNFLGtCQUFNLElBQUksTUFBTSwwQkFBMEIsT0FBTyxDQUFDLENBQUMsRUFBRTtBQUFBLFFBQ3pEO0FBQUEsTUFDRjtBQUVPLE1BQU0sdUNBQU4sTUFBOEU7QUFBQSxRQVFuRixNQUFNLDhCQUE4QixNQUFtRDtBQUVyRixpQkFBT0Msd0JBQXVCLE1BQU0sU0FBUyxJQUFJLENBQUM7QUFBQSxRQUNwRDtBQUFBLFFBRUEsTUFBTSxVQUFVLGNBQW1DLFNBQTBEO0FBQzNHLDJCQUFpQjtBQUNqQixjQUFJO0FBRUosY0FBSSxPQUFPLGlCQUFpQixVQUFVO0FBQ3BDLGdCQUFJLFFBQVE7QUFFVixzQkFBUSxNQUFNLFNBQVMsWUFBWTtBQUFBLFlBQ3JDLE9BQU87QUFHTCxzQkFBUSxNQUFNLEtBQUssOEJBQThCLFlBQVk7QUFBQSxZQUMvRDtBQUFBLFVBQ0YsT0FBTztBQUNMLG9CQUFRO0FBQUEsVUFDVjtBQUVBLFdBQUMsS0FBSyxXQUFXLEtBQUssWUFBWSxLQUFLLGFBQWEsS0FBSyxlQUFlLEtBQUssY0FBYyxJQUFJLE1BQU1DO0FBQUEsWUFDbkc7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUNBLHlCQUFlO0FBQUEsUUFDakI7QUFBQSxRQUVBLE1BQU0sVUFBeUI7QUFDN0IsaUJBQU9DLGdCQUFlLEtBQUssU0FBUztBQUFBLFFBQ3RDO0FBQUEsUUFFQSxNQUFNLElBQ0osT0FDQSxTQUNBLFNBQ29DO0FBQ3BDLDJCQUFpQjtBQUNqQixnQkFBTSxhQUF1QixDQUFDO0FBQzlCLGdCQUFNLGVBQXlCLENBQUM7QUFDaEMsaUJBQU8sUUFBUSxLQUFLLEVBQUUsUUFBUSxDQUFDLFFBQVE7QUFDckMsa0JBQU0sT0FBTyxJQUFJLENBQUM7QUFDbEIsa0JBQU0sU0FBUyxJQUFJLENBQUM7QUFDcEIsa0JBQU0sUUFBUSxLQUFLLFdBQVcsUUFBUSxJQUFJO0FBQzFDLGdCQUFJLFVBQVUsSUFBSTtBQUNoQixvQkFBTSxJQUFJLE1BQU0sa0JBQWtCLElBQUksR0FBRztBQUFBLFlBQzNDO0FBQ0EsdUJBQVcsS0FBSyxNQUFNO0FBQ3RCLHlCQUFhLEtBQUssS0FBSztBQUFBLFVBQ3pCLENBQUM7QUFFRCxnQkFBTSxjQUFvQyxDQUFDO0FBQzNDLGdCQUFNLGdCQUEwQixDQUFDO0FBQ2pDLGlCQUFPLFFBQVEsT0FBTyxFQUFFLFFBQVEsQ0FBQyxRQUFRO0FBQ3ZDLGtCQUFNLE9BQU8sSUFBSSxDQUFDO0FBQ2xCLGtCQUFNLFNBQVMsSUFBSSxDQUFDO0FBQ3BCLGtCQUFNLFFBQVEsS0FBSyxZQUFZLFFBQVEsSUFBSTtBQUMzQyxnQkFBSSxVQUFVLElBQUk7QUFDaEIsb0JBQU0sSUFBSSxNQUFNLG1CQUFtQixJQUFJLEdBQUc7QUFBQSxZQUM1QztBQUNBLHdCQUFZLEtBQUssTUFBTTtBQUN2QiwwQkFBYyxLQUFLLEtBQUs7QUFBQSxVQUMxQixDQUFDO0FBRUQsZ0JBQU0sU0FBUyxXQUFXO0FBQUEsWUFBSSxDQUFDLEdBQUcsTUFDaEMscUJBQXFCLEdBQUcsTUFBTSxVQUFVLEtBQUssV0FBVyxhQUFhLENBQUMsQ0FBQyxDQUFDLEdBQUc7QUFBQSxVQUM3RTtBQUNBLGdCQUFNLFVBQVUsWUFBWTtBQUFBLFlBQUksQ0FBQyxHQUFHLE1BQ2xDLElBQUkscUJBQXFCLEdBQUcsTUFBTSxXQUFXLEtBQUssWUFBWSxjQUFjLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSTtBQUFBLFVBQ3hGO0FBRUEsZ0JBQU0sVUFBVSxNQUFNQyxLQUFJLEtBQUssV0FBVyxjQUFjLFFBQVEsZUFBZSxTQUFTLE9BQU87QUFFL0YsZ0JBQU0sWUFBdUMsQ0FBQztBQUM5QyxtQkFBUyxJQUFJLEdBQUcsSUFBSSxRQUFRLFFBQVEsS0FBSztBQUN2QyxzQkFBVSxLQUFLLFlBQVksY0FBYyxDQUFDLENBQUMsQ0FBQyxJQUFJLFlBQVksQ0FBQyxLQUFLLHFCQUFxQixRQUFRLENBQUMsQ0FBQztBQUFBLFVBQ25HO0FBQ0EseUJBQWU7QUFDZixpQkFBTztBQUFBLFFBQ1Q7QUFBQSxRQUVBLGlCQUF1QjtBQUFBLFFBRXZCO0FBQUEsUUFFQSxlQUFxQjtBQUNuQixlQUFLQyxjQUFhLEtBQUssU0FBUztBQUFBLFFBQ2xDO0FBQUEsTUFDRjtBQUFBO0FBQUE7OztBQ3pKQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxNQWNhLGlCQTRDQSwrQkFxQ0E7QUEvRmI7QUFBQTtBQUFBO0FBR0E7QUFFQTtBQUNBO0FBUU8sTUFBTSxrQkFBa0IsTUFBWTtBQUN6QyxZQUFJLE9BQU9DLEtBQUksS0FBSyxnQkFBZ0IsWUFBWUEsS0FBSSxLQUFLLGNBQWMsR0FBRztBQUN4RSxVQUFBQSxLQUFJLEtBQUssY0FBYztBQUFBLFFBQ3pCO0FBRUEsY0FBTSxPQUFPQSxLQUFJLEtBQUs7QUFDdEIsWUFBSSxPQUFPLFNBQVMsYUFBYSxTQUFTLFVBQWEsU0FBUyxXQUFXLFNBQVMsV0FBVztBQUU3RixrQkFBUTtBQUFBLFlBQ04scURBQXFELElBQUk7QUFBQSxVQUMzRDtBQUNBLFVBQUFBLEtBQUksS0FBSyxPQUFPO0FBQUEsUUFDbEI7QUFFQSxZQUFJLE9BQU9BLEtBQUksS0FBSyxVQUFVLFdBQVc7QUFDdkMsVUFBQUEsS0FBSSxLQUFLLFFBQVE7QUFBQSxRQUNuQjtBQUVBLFlBQUksT0FBT0EsS0FBSSxLQUFLLFVBQVUsV0FBVztBQUN2QyxVQUFBQSxLQUFJLEtBQUssUUFBUTtBQUFBLFFBQ25CO0FBRUEsWUFBSSxPQUFPQSxLQUFJLEtBQUssZUFBZSxZQUFZLENBQUMsT0FBTyxVQUFVQSxLQUFJLEtBQUssVUFBVSxLQUFLQSxLQUFJLEtBQUssY0FBYyxHQUFHO0FBWWpILGNBQUksT0FBTyxTQUFTLGVBQWUsQ0FBQyxLQUFLLHFCQUFxQjtBQUM1RCxZQUFBQSxLQUFJLEtBQUssYUFBYTtBQUFBLFVBQ3hCLE9BQU87QUFDTCxrQkFBTSxxQkFDSixPQUFPLGNBQWMsY0FBYyxVQUFRLFNBQVMsRUFBRSxLQUFLLEVBQUUsU0FBUyxVQUFVO0FBQ2xGLFlBQUFBLEtBQUksS0FBSyxhQUFhLEtBQUssSUFBSSxHQUFHLEtBQUssTUFBTSxzQkFBc0IsS0FBSyxDQUFDLENBQUM7QUFBQSxVQUM1RTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRU8sTUFBTSxnQ0FBTixNQUF1RDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxRQVM1RCxNQUFNLEtBQUssYUFBb0M7QUFFN0MsMEJBQWdCO0FBR2hCLGdCQUFNLG1DQUFtQztBQUd6QyxnQkFBTSxnQkFBZ0IsV0FBVztBQUFBLFFBQ25DO0FBQUEsUUFTQSxNQUFNLDhCQUNKLGNBQ0EsU0FDa0M7QUFDbEMsZ0JBQU0sVUFBVSxJQUFJLHFDQUFxQztBQUN6RCxnQkFBTSxRQUFRLFVBQVUsY0FBYyxPQUFPO0FBQzdDLGlCQUFPO0FBQUEsUUFDVDtBQUFBLE1BQ0Y7QUFFTyxNQUFNLGNBQWMsSUFBSSw4QkFBOEI7QUFBQTtBQUFBOzs7QUMvRjdEO0FBQUE7QUFBQSw0QkFBQUM7QUFBQSxJQUFBO0FBQUE7QUFBQTtBQUFBLGtCQUFBQztBQUFBLElBQUE7QUFBQSxlQUFBQztBQUFBLElBQUE7QUFBQTtBQVNBO0FBQ0E7QUFHQTs7O0FDUE8sTUFBTUMsV0FBVTs7O0FES3ZCLE1BQU8sZ0JBQVE7QUFLZixNQUFJLE9BQTJCO0FBQzdCLFVBQU0sZ0JBQWdCLEtBQTRCO0FBQ2xELG9CQUFnQixTQUFTLGVBQWUsR0FBRztBQUFBLEVBQzdDO0FBRUEsTUFBSSxNQUEwQjtBQUM1QixVQUFNQyxlQUFjLDBEQUEwQjtBQUM5QyxRQUFJLE1BQTBCO0FBQzVCLHNCQUFnQixVQUFVQSxjQUFhLENBQUM7QUFDeEMsc0JBQWdCLFNBQVNBLGNBQWEsQ0FBQztBQUFBLElBQ3pDO0FBQ0Esb0JBQWdCLE9BQU9BLGNBQWEsRUFBRTtBQUN0QyxvQkFBZ0IsUUFBUUEsY0FBYSxFQUFFO0FBQUEsRUFDekM7QUFFQSxTQUFPLGVBQWVDLEtBQUksVUFBVSxPQUFPLEVBQUUsT0FBT0MsVUFBUyxZQUFZLEtBQUssQ0FBQzsiLAogICJuYW1lcyI6IFsiaSIsICJlbnYiLCAiRmxvYXQxNkFycmF5IiwgIlRlbnNvciIsICJUZW5zb3IiLCAiSW5mZXJlbmNlU2Vzc2lvbiIsICJJbmZlcmVuY2VTZXNzaW9uIiwgIlRlbnNvciIsICJlbnYiLCAiZW52IiwgIndhc20iLCAid2FzbSIsICJ3YXNtIiwgImxvY2F0aW9uIiwgInBhZCIsICJ0ZW5zb3IiLCAiZW52IiwgIm1sQ29udGV4dEluZGV4IiwgIndhc20iLCAiaW5pdCIsICJvZmZzZXRzIiwgImluZGljZXMiLCAiaW1wbCIsICJ2YWxpZGF0ZUlucHV0cyIsICJyZWR1Y2VPcHMiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAiZW52IiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgImEiLCAiYiIsICJ2YWxpZGF0ZUlucHV0cyIsICJpIiwgImlucHV0VmFyaWFibGUiLCAidHJhbnNwb3NlIiwgIm91dHB1dFZhcmlhYmxlIiwgImlubmVyRWxlbWVudFNpemUiLCAicGFkIiwgInZhbGlkYXRlSW5wdXRzIiwgImNvbnZJbnB1dHMiLCAidHJhbnNwb3NlZFdlaWdodCIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJwZXJtRnVuY3Rpb25Cb2R5IiwgInN5bWJvbCIsICJyZWR1Y2VPcHMiLCAidmFsaWRhdGVJbnB1dHMiLCAiY2FsY3VsYXRlT3V0cHV0U2hhcGUiLCAiZmFzdEdlbHUiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAidmFsaWRhdGVJbnB1dHMiLCAiaW5wdXRzIiwgIm91dHB1dFNpemUiLCAidmFsaWRhdGVJbnB1dHMiLCAid2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlIiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgIndlaWdodFRyYW5zcG9zZUF0dHJpYnV0ZSIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJkYXRhVHlwZSIsICJ2YWxpZGF0ZUlucHV0cyIsICJ2YWxpZGF0ZUlucHV0cyIsICJlbnYiLCAidmFsaWRhdGVJbnB1dHMiLCAiZW52IiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgInZhbGlkYXRlSW5wdXRzIiwgImNvbXBvbmVudHMiLCAidmFsaWRhdGVJbnB1dHMiLCAiZ2V0T3V0cHV0U2hhcGUiLCAiYSIsICJiIiwgImMiLCAiZmFzdEdlbHUiLCAiZW52IiwgImkiLCAiZW52IiwgImVudiIsICJ3YXNtIiwgImxvY2F0aW9uIiwgImluZGV4IiwgInRlbnNvciIsICJlcnJvckNvZGUiLCAiaSIsICJpbml0aWFsaXppbmciLCAiaW5pdGlhbGl6ZWQiLCAiYWJvcnRlZCIsICJjb3B5RnJvbUV4dGVybmFsQnVmZmVyIiwgImNyZWF0ZVNlc3Npb24iLCAicmVsZWFzZVNlc3Npb24iLCAicnVuIiwgImVuZFByb2ZpbGluZyIsICJlbnYiLCAiVGVuc29yIiwgImNvcHlGcm9tRXh0ZXJuYWxCdWZmZXIiLCAiY3JlYXRlU2Vzc2lvbiIsICJyZWxlYXNlU2Vzc2lvbiIsICJydW4iLCAiZW5kUHJvZmlsaW5nIiwgImVudiIsICJJbmZlcmVuY2VTZXNzaW9uIiwgIlRlbnNvciIsICJlbnYiLCAidmVyc2lvbiIsICJ3YXNtQmFja2VuZCIsICJlbnYiLCAidmVyc2lvbiJdCn0K